about summary refs log tree commit diff
path: root/compiler/rustc_span/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-28 05:15:56 +0000
committerbors <bors@rust-lang.org>2023-08-28 05:15:56 +0000
commit41cb42a370b35707a75c79ff9ab6af1191b638fb (patch)
treec36b9d3ee534c593067b7b9f1c8e00c1d48e9e3d /compiler/rustc_span/src
parentf7dd70c3c9edeecdbedf4d80c83317c50a817756 (diff)
parentf26293dca4a4bc2fa6158964546617a6a34da639 (diff)
downloadrust-41cb42a370b35707a75c79ff9ab6af1191b638fb.tar.gz
rust-41cb42a370b35707a75c79ff9ab6af1191b638fb.zip
Auto merge of #115296 - saethlin:dont-duplicate-allocs, r=jackh726
Load include_bytes! directly into an Lrc

This PR deletes an innocent-looking `.into()` that was converting from a `Vec<u8>` to `Lrc<[u8]>`. This has significant runtime and memory overhead when using `include_bytes!` to pull in a large binary file.
Diffstat (limited to 'compiler/rustc_span/src')
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/source_map.rs21
2 files changed, 19 insertions, 4 deletions
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index efaed0f68ce..62fe49fe2a2 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -21,6 +21,8 @@
 #![feature(rustc_attrs)]
 #![feature(let_chains)]
 #![feature(round_char_boundary)]
+#![feature(read_buf)]
+#![feature(new_uninit)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 #![allow(internal_features)]
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 983b2ab04a4..1cff021ba41 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -24,6 +24,8 @@ use std::sync::atomic::Ordering;
 
 use std::fs;
 use std::io;
+use std::io::BorrowedBuf;
+use std::io::Read;
 
 #[cfg(test)]
 mod tests;
@@ -101,10 +103,13 @@ pub trait FileLoader {
     fn file_exists(&self, path: &Path) -> bool;
 
     /// Read the contents of a UTF-8 file into memory.
+    /// This function must return a String because we normalize
+    /// source files, which may require resizing.
     fn read_file(&self, path: &Path) -> io::Result<String>;
 
     /// Read the contents of a potentially non-UTF-8 file into memory.
-    fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>>;
+    /// We don't normalize binary files, so we can start in an Lrc.
+    fn read_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>>;
 }
 
 /// A FileLoader that uses std::fs to load real files.
@@ -119,8 +124,16 @@ impl FileLoader for RealFileLoader {
         fs::read_to_string(path)
     }
 
-    fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
-        fs::read(path)
+    fn read_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>> {
+        let mut file = fs::File::open(path)?;
+        let len = file.metadata()?.len();
+
+        let mut bytes = Lrc::new_uninit_slice(len as usize);
+        let mut buf = BorrowedBuf::from(Lrc::get_mut(&mut bytes).unwrap());
+        file.read_buf_exact(buf.unfilled())?;
+        // SAFETY: If the read_buf_exact call returns Ok(()), then we have
+        // read len bytes and initialized the buffer.
+        Ok(unsafe { bytes.assume_init() })
     }
 }
 
@@ -228,7 +241,7 @@ impl SourceMap {
     ///
     /// Unlike `load_file`, guarantees that no normalization like BOM-removal
     /// takes place.
-    pub fn load_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
+    pub fn load_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>> {
         let bytes = self.file_loader.read_binary_file(path)?;
 
         // We need to add file to the `SourceMap`, so that it is present