Allow taking an OwningRef of the crate metadata blob.

This commit is contained in:
Michael Woerister 2021-07-20 13:51:21 +02:00
parent 9f85cd6f2a
commit 0debea1377
2 changed files with 62 additions and 18 deletions

View file

@ -48,7 +48,26 @@ use rustc_span::hygiene::HygieneDecodeContext;
mod cstore_impl; mod cstore_impl;
crate struct MetadataBlob(MetadataRef); /// A reference to the raw binary version of crate metadata.
/// A `MetadataBlob` internally is just a reference counted pointer to
/// the actual data, so cloning it is cheap.
#[derive(Clone)]
crate struct MetadataBlob(Lrc<MetadataRef>);
// This is needed so we can create an OwningRef into the blob.
// The data behind a `MetadataBlob` has a stable address because it
// contained within an Rc/Arc.
unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {}
// This is needed so we can create an OwningRef into the blob.
impl std::ops::Deref for MetadataBlob {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
&self.0[..]
}
}
// A map from external crate numbers (as decoded from some crate file) to // A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external // local crate numbers (as generated during this session). Each external
@ -134,6 +153,7 @@ struct ImportedSourceFile {
pub(super) struct DecodeContext<'a, 'tcx> { pub(super) struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>, opaque: opaque::Decoder<'a>,
cdata: Option<CrateMetadataRef<'a>>, cdata: Option<CrateMetadataRef<'a>>,
blob: &'a MetadataBlob,
sess: Option<&'tcx Session>, sess: Option<&'tcx Session>,
tcx: Option<TyCtxt<'tcx>>, tcx: Option<TyCtxt<'tcx>>,
@ -148,7 +168,11 @@ pub(super) struct DecodeContext<'a, 'tcx> {
/// Abstract over the various ways one can create metadata decoders. /// Abstract over the various ways one can create metadata decoders.
pub(super) trait Metadata<'a, 'tcx>: Copy { pub(super) trait Metadata<'a, 'tcx>: Copy {
fn raw_bytes(self) -> &'a [u8]; fn blob(self) -> &'a MetadataBlob;
#[inline]
fn raw_bytes(self) -> &'a [u8] {
self.blob()
}
fn cdata(self) -> Option<CrateMetadataRef<'a>> { fn cdata(self) -> Option<CrateMetadataRef<'a>> {
None None
} }
@ -164,6 +188,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
DecodeContext { DecodeContext {
opaque: opaque::Decoder::new(self.raw_bytes(), pos), opaque: opaque::Decoder::new(self.raw_bytes(), pos),
cdata: self.cdata(), cdata: self.cdata(),
blob: self.blob(),
sess: self.sess().or(tcx.map(|tcx| tcx.sess)), sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
tcx, tcx,
last_source_file_index: 0, last_source_file_index: 0,
@ -176,17 +201,19 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
} }
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
fn raw_bytes(self) -> &'a [u8] { #[inline]
&self.0 fn blob(self) -> &'a MetadataBlob {
self
} }
} }
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
fn raw_bytes(self) -> &'a [u8] { #[inline]
let (blob, _) = self; fn blob(self) -> &'a MetadataBlob {
&blob.0 self.0
} }
#[inline]
fn sess(self) -> Option<&'tcx Session> { fn sess(self) -> Option<&'tcx Session> {
let (_, sess) = self; let (_, sess) = self;
Some(sess) Some(sess)
@ -194,33 +221,41 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
} }
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> { impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
fn raw_bytes(self) -> &'a [u8] { #[inline]
self.blob.raw_bytes() fn blob(self) -> &'a MetadataBlob {
&self.blob
} }
#[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> { fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self) Some(*self)
} }
} }
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) { impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
fn raw_bytes(self) -> &'a [u8] { #[inline]
self.0.raw_bytes() fn blob(self) -> &'a MetadataBlob {
&self.0.blob
} }
#[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> { fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0) Some(*self.0)
} }
#[inline]
fn sess(self) -> Option<&'tcx Session> { fn sess(self) -> Option<&'tcx Session> {
Some(&self.1) Some(&self.1)
} }
} }
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
fn raw_bytes(self) -> &'a [u8] { #[inline]
self.0.raw_bytes() fn blob(self) -> &'a MetadataBlob {
&self.0.blob
} }
#[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> { fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0) Some(*self.0)
} }
#[inline]
fn tcx(self) -> Option<TyCtxt<'tcx>> { fn tcx(self) -> Option<TyCtxt<'tcx>> {
Some(self.1) Some(self.1)
} }
@ -246,12 +281,21 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> {
} }
impl<'a, 'tcx> DecodeContext<'a, 'tcx> { impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx.expect("missing TyCtxt in DecodeContext") debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext");
self.tcx.unwrap()
} }
fn cdata(&self) -> CrateMetadataRef<'a> { #[inline]
self.cdata.expect("missing CrateMetadata in DecodeContext") pub fn blob(&self) -> &'a MetadataBlob {
self.blob
}
#[inline]
pub fn cdata(&self) -> CrateMetadataRef<'a> {
debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
self.cdata.unwrap()
} }
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
@ -586,7 +630,7 @@ implement_ty_decoder!(DecodeContext<'a, 'tcx>);
impl MetadataBlob { impl MetadataBlob {
crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob {
MetadataBlob(metadata_ref) MetadataBlob(Lrc::new(metadata_ref))
} }
crate fn is_compatible(&self) -> bool { crate fn is_compatible(&self) -> bool {

View file

@ -199,7 +199,7 @@ where
debug!("Table::lookup: index={:?} len={:?}", i, self.meta); debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
let start = self.position.get(); let start = self.position.get();
let bytes = &metadata.raw_bytes()[start..start + self.meta]; let bytes = &metadata.blob()[start..start + self.meta];
<Option<T>>::maybe_read_from_bytes_at(bytes, i.index())? <Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
} }