about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYoshiki Matsuda <myskjp@gmail.com>2022-04-29 13:50:27 +0900
committerYoshiki Matsuda <myskjp@gmail.com>2022-07-02 22:51:42 +0900
commit336af60eae7cd272f702f0420723a733008f0161 (patch)
treec80653cdddf9f3c06327ba3397e463224c7fe428
parent8cfa7caac9bba5b83995040ebf313559e4e2186c (diff)
downloadrust-336af60eae7cd272f702f0420723a733008f0161.tar.gz
rust-336af60eae7cd272f702f0420723a733008f0161.zip
write to a temporary file in Decodable for EncodedMetadata
-rw-r--r--compiler/rustc_metadata/src/fs.rs14
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs37
2 files changed, 32 insertions, 19 deletions
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index fa97cda0aa3..f6373438491 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -80,7 +80,7 @@ pub fn encode_and_write_metadata(
     let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata");
 
     let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
-    let metadata_filename = if need_metadata_file {
+    let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
         if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) {
             tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
         }
@@ -90,14 +90,14 @@ pub fn encode_and_write_metadata(
                 .span_diagnostic
                 .emit_artifact_notification(&out_filename, "metadata");
         }
-        out_filename
+        (out_filename, None)
     } else {
-        metadata_filename
+        (metadata_filename, Some(metadata_tmpdir))
     };
-    let file = std::fs::File::open(metadata_filename).unwrap();
-    let metadata = EncodedMetadata::from_file(file).unwrap_or_else(|e| {
-        tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e))
-    });
+    let metadata =
+        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| {
+            tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e))
+        });
 
     let need_metadata_module = metadata_kind == MetadataKind::Compressed;
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 6e2044d4bb0..68da815dc30 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
+use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{
@@ -39,9 +40,11 @@ use rustc_span::{
 use rustc_target::abi::VariantIdx;
 use std::borrow::Borrow;
 use std::hash::Hash;
+use std::io::Write;
 use std::iter;
 use std::num::NonZeroUsize;
-use std::path::Path;
+use std::path::{Path, PathBuf};
+use tempfile::Builder as TempFileBuilder;
 use tracing::{debug, trace};
 
 pub(super) struct EncodeContext<'a, 'tcx> {
@@ -2138,25 +2141,25 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
 
 pub struct EncodedMetadata {
     mmap: Option<Mmap>,
-    decoded: Vec<u8>,
+    // We need to carry MaybeTempDir to avoid deleting the temporary
+    // directory while accessing the Mmap.
+    _temp_dir: Option<MaybeTempDir>,
 }
 
 impl EncodedMetadata {
     #[inline]
-    pub fn from_file(file: std::fs::File) -> std::io::Result<Self> {
+    pub fn from_path(path: PathBuf, temp_dir: Option<MaybeTempDir>) -> std::io::Result<Self> {
+        let file = std::fs::File::open(&path)?;
         let file_metadata = file.metadata()?;
         if file_metadata.len() == 0 {
-            return Ok(Self { mmap: None, decoded: Vec::new() });
+            return Ok(Self { mmap: None, _temp_dir: temp_dir });
         }
         let mmap = unsafe { Some(Mmap::map(file)?) };
-        Ok(Self { mmap, decoded: Vec::new() })
+        Ok(Self { mmap, _temp_dir: temp_dir })
     }
 
     #[inline]
     pub fn raw_data(&self) -> &[u8] {
-        if !self.decoded.is_empty() {
-            return &self.decoded;
-        }
         self.mmap.as_ref().map(|mmap| mmap.as_ref()).unwrap_or_default()
     }
 }
@@ -2170,9 +2173,19 @@ impl<S: Encoder> Encodable<S> for EncodedMetadata {
 
 impl<D: Decoder> Decodable<D> for EncodedMetadata {
     fn decode(d: &mut D) -> Self {
-        // FIXME: Write decorded data to a file and map to Mmap.
-        let decoded = Decodable::decode(d);
-        EncodedMetadata { mmap: None, decoded }
+        let temp_dir = TempFileBuilder::new().prefix("decoded").tempdir().unwrap();
+        let temp_dir = MaybeTempDir::new(temp_dir, false);
+        let filename = temp_dir.as_ref().join("decoded");
+        let file = std::fs::File::create(&filename).unwrap();
+        let mut file = std::io::BufWriter::new(file);
+
+        let len = d.read_usize();
+        for _ in 0..len {
+            file.write(&[d.read_u8()]).unwrap();
+        }
+        file.flush().unwrap();
+
+        Self::from_path(filename, Some(temp_dir)).unwrap()
     }
 }
 
@@ -2269,5 +2282,5 @@ pub fn provide(providers: &mut Providers) {
         },
 
         ..*providers
-    };
+    }
 }