Skip to content

Commit 2a5c4ba

Browse files
authored
Rollup merge of #110145 - WaffleLapkin:share_slice_of_bytes, r=Nilstrieb
Share slice of bytes r? `@Nilstrieb` cc `@noamtashma`
2 parents c0784db + a6197a5 commit 2a5c4ba

File tree

10 files changed

+64
-37
lines changed

10 files changed

+64
-37
lines changed

compiler/rustc_codegen_ssa/src/back/metadata.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ use snap::write::FrameEncoder;
1414

1515
use object::elf::NT_GNU_PROPERTY_TYPE_0;
1616
use rustc_data_structures::memmap::Mmap;
17-
use rustc_data_structures::owned_slice::try_slice_owned;
18-
use rustc_data_structures::sync::MetadataRef;
17+
use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
1918
use rustc_metadata::fs::METADATA_FILENAME;
2019
use rustc_metadata::EncodedMetadata;
2120
use rustc_session::cstore::MetadataLoader;
@@ -39,7 +38,7 @@ pub struct DefaultMetadataLoader;
3938
fn load_metadata_with(
4039
path: &Path,
4140
f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
42-
) -> Result<MetadataRef, String> {
41+
) -> Result<OwnedSlice, String> {
4342
let file =
4443
File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
4544

@@ -49,7 +48,7 @@ fn load_metadata_with(
4948
}
5049

5150
impl MetadataLoader for DefaultMetadataLoader {
52-
fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
51+
fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
5352
load_metadata_with(path, |data| {
5453
let archive = object::read::archive::ArchiveFile::parse(&*data)
5554
.map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
@@ -69,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader {
6968
})
7069
}
7170

72-
fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
71+
fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
7372
load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
7473
}
7574
}

compiler/rustc_codegen_ssa/src/traits/backend.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
use std::any::Any;
2+
13
use super::write::WriteBackendMethods;
24
use super::CodegenObject;
35
use crate::back::write::TargetMachineFactoryFn;
46
use crate::{CodegenResults, ModuleCodegen};
57

68
use rustc_ast::expand::allocator::AllocatorKind;
79
use rustc_data_structures::fx::FxHashMap;
10+
use rustc_data_structures::sync::{DynSend, DynSync};
811
use rustc_errors::ErrorGuaranteed;
912
use rustc_metadata::EncodedMetadata;
1013
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -20,11 +23,6 @@ use rustc_span::symbol::Symbol;
2023
use rustc_target::abi::call::FnAbi;
2124
use rustc_target::spec::Target;
2225

23-
pub use rustc_data_structures::sync::MetadataRef;
24-
25-
use rustc_data_structures::sync::{DynSend, DynSync};
26-
use std::any::Any;
27-
2826
pub trait BackendTypes {
2927
type Value: CodegenObject;
3028
type Function: CodegenObject;

compiler/rustc_data_structures/src/owned_slice.rs

+36-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::{borrow::Borrow, ops::Deref};
22

3+
use crate::sync::Lrc;
34
// Use our fake Send/Sync traits when on not parallel compiler,
45
// so that `OwnedSlice` only implements/requires Send/Sync
56
// for parallel compiler builds.
67
use crate::sync::{Send, Sync};
78

89
/// An owned slice.
910
///
10-
/// This is similar to `Box<[u8]>` but allows slicing and using anything as the
11+
/// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
1112
/// backing buffer.
1213
///
1314
/// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
1617
///
1718
/// This is essentially a replacement for `owning_ref` which is a lot simpler
1819
/// and even sound! 🌸
20+
#[derive(Clone)]
1921
pub struct OwnedSlice {
2022
/// This is conceptually a `&'self.owner [u8]`.
2123
bytes: *const [u8],
@@ -31,7 +33,7 @@ pub struct OwnedSlice {
3133
// \/
3234
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
3335
#[expect(dead_code)]
34-
owner: Box<dyn Send + Sync>,
36+
owner: Lrc<dyn Send + Sync>,
3537
}
3638

3739
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,23 +74,50 @@ where
7274
O: Send + Sync + 'static,
7375
F: FnOnce(&O) -> Result<&[u8], E>,
7476
{
75-
// We box the owner of the bytes, so it doesn't move.
77+
// We wrap the owner of the bytes in, so it doesn't move.
7678
//
7779
// Since the owner does not move and we don't access it in any way
78-
// before drop, there is nothing that can invalidate the bytes pointer.
80+
// before dropping, there is nothing that can invalidate the bytes pointer.
7981
//
8082
// Thus, "extending" the lifetime of the reference returned from `F` is fine.
8183
// We pretend that we pass it a reference that lives as long as the returned slice.
8284
//
8385
// N.B. the HRTB on the `slicer` is important — without it the caller could provide
8486
// a short lived slice, unrelated to the owner.
8587

86-
let owner = Box::new(owner);
88+
let owner = Lrc::new(owner);
8789
let bytes = slicer(&*owner)?;
8890

8991
Ok(OwnedSlice { bytes, owner })
9092
}
9193

94+
impl OwnedSlice {
95+
/// Slice this slice by `slicer`.
96+
///
97+
/// # Examples
98+
///
99+
/// ```rust
100+
/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
101+
/// let vec = vec![1, 2, 3, 4];
102+
///
103+
/// // Identical to slicing via `&v[1..3]` but produces an owned slice
104+
/// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
105+
/// assert_eq!(&*slice, [1, 2, 3, 4]);
106+
///
107+
/// let slice = slice.slice(|slice| &slice[1..][..2]);
108+
/// assert_eq!(&*slice, [2, 3]);
109+
/// ```
110+
///
111+
pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
112+
// This is basically identical to `try_slice_owned`,
113+
// `slicer` can only return slices of its argument or some static data,
114+
// both of which are valid while `owner` is alive.
115+
116+
let bytes = slicer(&self);
117+
OwnedSlice { bytes, ..self }
118+
}
119+
}
120+
92121
impl Deref for OwnedSlice {
93122
type Target = [u8];
94123

@@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
108137
}
109138
}
110139

111-
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send`
140+
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
112141
#[cfg(parallel_compiler)]
113142
unsafe impl Send for OwnedSlice {}
114143

115-
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync`
144+
// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
116145
#[cfg(parallel_compiler)]
117146
unsafe impl Sync for OwnedSlice {}
118147

compiler/rustc_data_structures/src/owned_slice/tests.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn static_storage() {
2626
}
2727

2828
#[test]
29-
fn slice_the_slice() {
29+
fn slice_owned_the_slice() {
3030
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
3131
let slice = slice_owned(slice, |s| &s[1..][..4]);
3232
let slice = slice_owned(slice, |s| s);
@@ -35,6 +35,16 @@ fn slice_the_slice() {
3535
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
3636
}
3737

38+
#[test]
39+
fn slice_the_slice() {
40+
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
41+
.slice(|s| &s[1..][..4])
42+
.slice(|s| s)
43+
.slice(|s| &s[1..]);
44+
45+
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
46+
}
47+
3848
#[test]
3949
fn try_and_fail() {
4050
let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));

compiler/rustc_data_structures/src/sync.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
//! [^2] `MTLockRef` is a typedef.
4141
4242
pub use crate::marker::*;
43-
use crate::owned_slice::OwnedSlice;
4443
use std::collections::HashMap;
4544
use std::hash::{BuildHasher, Hash};
4645
use std::ops::{Deref, DerefMut};
@@ -92,6 +91,7 @@ mod mode {
9291
}
9392

9493
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
94+
9595
cfg_if! {
9696
if #[cfg(not(parallel_compiler))] {
9797
pub unsafe auto trait Send {}
@@ -244,8 +244,6 @@ cfg_if! {
244244
r
245245
}
246246

247-
pub type MetadataRef = OwnedSlice;
248-
249247
pub use std::rc::Rc as Lrc;
250248
pub use std::rc::Weak as Weak;
251249
pub use std::cell::Ref as ReadGuard;
@@ -517,8 +515,6 @@ cfg_if! {
517515
}
518516
}
519517

520-
pub type MetadataRef = OwnedSlice;
521-
522518
/// This makes locks panic if they are already held.
523519
/// It is only useful when you are running in a single thread
524520
const ERROR_CHECKING: bool = false;

compiler/rustc_metadata/src/locator.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
220220
use rustc_data_structures::memmap::Mmap;
221221
use rustc_data_structures::owned_slice::slice_owned;
222222
use rustc_data_structures::svh::Svh;
223-
use rustc_data_structures::sync::MetadataRef;
224223
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
225224
use rustc_fs_util::try_canonicalize;
226225
use rustc_session::config::{self, CrateType};
@@ -782,7 +781,7 @@ fn get_metadata_section<'p>(
782781
if !filename.exists() {
783782
return Err(MetadataError::NotPresent(filename));
784783
}
785-
let raw_bytes: MetadataRef = match flavor {
784+
let raw_bytes = match flavor {
786785
CrateFlavor::Rlib => {
787786
loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
788787
}
@@ -843,7 +842,7 @@ fn get_metadata_section<'p>(
843842
slice_owned(mmap, Deref::deref)
844843
}
845844
};
846-
let blob = MetadataBlob::new(raw_bytes);
845+
let blob = MetadataBlob(raw_bytes);
847846
if blob.is_compatible() {
848847
Ok(blob)
849848
} else {

compiler/rustc_metadata/src/rmeta/decoder.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::rmeta::*;
77
use rustc_ast as ast;
88
use rustc_data_structures::captures::Captures;
99
use rustc_data_structures::fx::FxHashMap;
10+
use rustc_data_structures::owned_slice::OwnedSlice;
1011
use rustc_data_structures::svh::Svh;
1112
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
1213
use rustc_data_structures::unhash::UnhashMap;
@@ -50,7 +51,7 @@ mod cstore_impl;
5051
/// A `MetadataBlob` internally is just a reference counted pointer to
5152
/// the actual data, so cloning it is cheap.
5253
#[derive(Clone)]
53-
pub(crate) struct MetadataBlob(Lrc<MetadataRef>);
54+
pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
5455

5556
impl std::ops::Deref for MetadataBlob {
5657
type Target = [u8];
@@ -660,10 +661,6 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
660661
implement_ty_decoder!(DecodeContext<'a, 'tcx>);
661662

662663
impl MetadataBlob {
663-
pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
664-
MetadataBlob(Lrc::new(metadata_ref))
665-
}
666-
667664
pub(crate) fn is_compatible(&self) -> bool {
668665
self.blob().starts_with(METADATA_HEADER)
669666
}

compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::rmeta::DecodeContext;
22
use crate::rmeta::EncodeContext;
3-
use rustc_data_structures::owned_slice::slice_owned;
43
use rustc_data_structures::owned_slice::OwnedSlice;
54
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
65
use rustc_middle::parameterized_over_tcx;
@@ -47,7 +46,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
4746
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
4847
let len = d.read_usize();
4948
let pos = d.position();
50-
let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]);
49+
let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
5150

5251
// Although we already have the data we need via the `OwnedSlice`, we still need
5352
// to advance the `DecodeContext`'s position so it's in a valid state after

compiler/rustc_metadata/src/rmeta/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use table::TableBuilder;
77
use rustc_ast as ast;
88
use rustc_attr as attr;
99
use rustc_data_structures::svh::Svh;
10-
use rustc_data_structures::sync::MetadataRef;
1110
use rustc_hir as hir;
1211
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
1312
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};

compiler/rustc_session/src/cstore.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use crate::search_paths::PathKind;
66
use crate::utils::NativeLibKind;
77
use crate::Session;
88
use rustc_ast as ast;
9-
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock};
9+
use rustc_data_structures::owned_slice::OwnedSlice;
10+
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, RwLock};
1011
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
1112
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
1213
use rustc_span::hygiene::{ExpnHash, ExpnId};
@@ -203,8 +204,8 @@ pub enum ExternCrateSource {
203204
/// metadata in library -- this trait just serves to decouple rustc_metadata from
204205
/// the archive reader, which depends on LLVM.
205206
pub trait MetadataLoader: std::fmt::Debug {
206-
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
207-
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
207+
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
208+
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
208209
}
209210

210211
pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;

0 commit comments

Comments
 (0)