Skip to content

Commit 41cb42a

Browse files
committed
Auto merge of rust-lang#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.
2 parents f7dd70c + f26293d commit 41cb42a

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Diff for: compiler/rustc_builtin_macros/src/source_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub fn expand_include_bytes(
217217
};
218218
match cx.source_map().load_binary_file(&file) {
219219
Ok(bytes) => {
220-
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes.into()));
220+
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
221221
base::MacEager::expr(expr)
222222
}
223223
Err(e) => {

Diff for: compiler/rustc_span/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#![feature(rustc_attrs)]
2222
#![feature(let_chains)]
2323
#![feature(round_char_boundary)]
24+
#![feature(read_buf)]
25+
#![feature(new_uninit)]
2426
#![deny(rustc::untranslatable_diagnostic)]
2527
#![deny(rustc::diagnostic_outside_of_impl)]
2628
#![allow(internal_features)]

Diff for: compiler/rustc_span/src/source_map.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use std::sync::atomic::Ordering;
2424

2525
use std::fs;
2626
use std::io;
27+
use std::io::BorrowedBuf;
28+
use std::io::Read;
2729

2830
#[cfg(test)]
2931
mod tests;
@@ -101,10 +103,13 @@ pub trait FileLoader {
101103
fn file_exists(&self, path: &Path) -> bool;
102104

103105
/// Read the contents of a UTF-8 file into memory.
106+
/// This function must return a String because we normalize
107+
/// source files, which may require resizing.
104108
fn read_file(&self, path: &Path) -> io::Result<String>;
105109

106110
/// Read the contents of a potentially non-UTF-8 file into memory.
107-
fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>>;
111+
/// We don't normalize binary files, so we can start in an Lrc.
112+
fn read_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>>;
108113
}
109114

110115
/// A FileLoader that uses std::fs to load real files.
@@ -119,8 +124,16 @@ impl FileLoader for RealFileLoader {
119124
fs::read_to_string(path)
120125
}
121126

122-
fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
123-
fs::read(path)
127+
fn read_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>> {
128+
let mut file = fs::File::open(path)?;
129+
let len = file.metadata()?.len();
130+
131+
let mut bytes = Lrc::new_uninit_slice(len as usize);
132+
let mut buf = BorrowedBuf::from(Lrc::get_mut(&mut bytes).unwrap());
133+
file.read_buf_exact(buf.unfilled())?;
134+
// SAFETY: If the read_buf_exact call returns Ok(()), then we have
135+
// read len bytes and initialized the buffer.
136+
Ok(unsafe { bytes.assume_init() })
124137
}
125138
}
126139

@@ -228,7 +241,7 @@ impl SourceMap {
228241
///
229242
/// Unlike `load_file`, guarantees that no normalization like BOM-removal
230243
/// takes place.
231-
pub fn load_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
244+
pub fn load_binary_file(&self, path: &Path) -> io::Result<Lrc<[u8]>> {
232245
let bytes = self.file_loader.read_binary_file(path)?;
233246

234247
// We need to add file to the `SourceMap`, so that it is present

0 commit comments

Comments
 (0)