Switch OwnedSlice to use Lrc & remove Lrc from MetadataBlob

This commit is contained in:
Maybe Waffle 2023-04-10 14:33:33 +00:00
parent 2eef27a6c1
commit 086c08d86a
6 changed files with 47 additions and 13 deletions

View File

@ -1,5 +1,6 @@
use std::{borrow::Borrow, ops::Deref}; use std::{borrow::Borrow, ops::Deref};
use crate::sync::Lrc;
// Use our fake Send/Sync traits when on not parallel compiler, // Use our fake Send/Sync traits when on not parallel compiler,
// so that `OwnedSlice` only implements/requires Send/Sync // so that `OwnedSlice` only implements/requires Send/Sync
// for parallel compiler builds. // for parallel compiler builds.
@ -7,7 +8,7 @@ use crate::sync::{Send, Sync};
/// An owned slice. /// An owned slice.
/// ///
/// This is similar to `Box<[u8]>` but allows slicing and using anything as the /// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
/// backing buffer. /// backing buffer.
/// ///
/// See [`slice_owned`] for `OwnedSlice` construction and examples. /// See [`slice_owned`] for `OwnedSlice` construction and examples.
@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
/// ///
/// This is essentially a replacement for `owning_ref` which is a lot simpler /// This is essentially a replacement for `owning_ref` which is a lot simpler
/// and even sound! 🌸 /// and even sound! 🌸
#[derive(Clone)]
pub struct OwnedSlice { pub struct OwnedSlice {
/// This is conceptually a `&'self.owner [u8]`. /// This is conceptually a `&'self.owner [u8]`.
bytes: *const [u8], bytes: *const [u8],
@ -31,7 +33,7 @@ pub struct OwnedSlice {
// \/ // \/
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770) // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
#[expect(dead_code)] #[expect(dead_code)]
owner: Box<dyn Send + Sync>, owner: Lrc<dyn Send + Sync>,
} }
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function. /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@ -83,12 +85,39 @@ where
// N.B. the HRTB on the `slicer` is important — without it the caller could provide // N.B. the HRTB on the `slicer` is important — without it the caller could provide
// a short lived slice, unrelated to the owner. // a short lived slice, unrelated to the owner.
let owner = Box::new(owner); let owner = Lrc::new(owner);
let bytes = slicer(&*owner)?; let bytes = slicer(&*owner)?;
Ok(OwnedSlice { bytes, owner }) Ok(OwnedSlice { bytes, owner })
} }
impl OwnedSlice {
/// Slice this slice by `slicer`.
///
/// # Examples
///
/// ```rust
/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
/// let vec = vec![1, 2, 3, 4];
///
/// // Identical to slicing via `&v[1..3]` but produces an owned slice
/// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
/// assert_eq!(&*slice, [1, 2, 3, 4]);
///
/// let slice = slice.slice(|slice| &slice[1..][..2]);
/// assert_eq!(&*slice, [2, 3]);
/// ```
///
pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
// This is basically identical to `try_slice_owned`,
// `slicer` can only return slices of its argument or some static data,
// both of which are valid while `owner` is alive.
let bytes = slicer(&self);
OwnedSlice { bytes, ..self }
}
}
impl Deref for OwnedSlice { impl Deref for OwnedSlice {
type Target = [u8]; type Target = [u8];

View File

@ -26,7 +26,7 @@ fn static_storage() {
} }
#[test] #[test]
fn slice_the_slice() { fn slice_owned_the_slice() {
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice); let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
let slice = slice_owned(slice, |s| &s[1..][..4]); let slice = slice_owned(slice, |s| &s[1..][..4]);
let slice = slice_owned(slice, |s| s); let slice = slice_owned(slice, |s| s);
@ -35,6 +35,16 @@ fn slice_the_slice() {
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]); assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
} }
#[test]
fn slice_the_slice() {
let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
.slice(|s| &s[1..][..4])
.slice(|s| s)
.slice(|s| &s[1..]);
assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
}
#[test] #[test]
fn try_and_fail() { fn try_and_fail() {
let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(())); let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));

View File

@ -843,7 +843,7 @@ fn get_metadata_section<'p>(
slice_owned(mmap, Deref::deref) slice_owned(mmap, Deref::deref)
} }
}; };
let blob = MetadataBlob::new(raw_bytes); let blob = MetadataBlob(raw_bytes);
if blob.is_compatible() { if blob.is_compatible() {
Ok(blob) Ok(blob)
} else { } else {

View File

@ -7,6 +7,7 @@ use crate::rmeta::*;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
use rustc_data_structures::unhash::UnhashMap; use rustc_data_structures::unhash::UnhashMap;
@ -50,7 +51,7 @@ mod cstore_impl;
/// A `MetadataBlob` internally is just a reference counted pointer to /// A `MetadataBlob` internally is just a reference counted pointer to
/// the actual data, so cloning it is cheap. /// the actual data, so cloning it is cheap.
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct MetadataBlob(Lrc<MetadataRef>); pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
impl std::ops::Deref for MetadataBlob { impl std::ops::Deref for MetadataBlob {
type Target = [u8]; type Target = [u8];
@ -660,10 +661,6 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
implement_ty_decoder!(DecodeContext<'a, 'tcx>); implement_ty_decoder!(DecodeContext<'a, 'tcx>);
impl MetadataBlob { impl MetadataBlob {
pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
MetadataBlob(Lrc::new(metadata_ref))
}
pub(crate) fn is_compatible(&self) -> bool { pub(crate) fn is_compatible(&self) -> bool {
self.blob().starts_with(METADATA_HEADER) self.blob().starts_with(METADATA_HEADER)
} }

View File

@ -1,6 +1,5 @@
use crate::rmeta::DecodeContext; use crate::rmeta::DecodeContext;
use crate::rmeta::EncodeContext; use crate::rmeta::EncodeContext;
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
use rustc_middle::parameterized_over_tcx; use rustc_middle::parameterized_over_tcx;
@ -47,7 +46,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
let len = d.read_usize(); let len = d.read_usize();
let pos = d.position(); let pos = d.position();
let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
// Although we already have the data we need via the `OwnedSlice`, we still need // Although we already have the data we need via the `OwnedSlice`, we still need
// to advance the `DecodeContext`'s position so it's in a valid state after // to advance the `DecodeContext`'s position so it's in a valid state after

View File

@ -7,7 +7,6 @@ use table::TableBuilder;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap}; use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};