Make metadata references Send + Sync
This commit is contained in:
parent
e8af0f4c1f
commit
62089c335f
@ -37,13 +37,12 @@
|
||||
use std::any::Any;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use rustc_data_structures::owning_ref::ErasedBoxRef;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use rustc_back::target::Target;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::{MetadataRef, Lrc};
|
||||
|
||||
pub use self::NativeLibraryKind::*;
|
||||
|
||||
@ -187,11 +186,11 @@ pub trait MetadataLoader {
|
||||
fn get_rlib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
-> Result<MetadataRef, String>;
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
-> Result<MetadataRef, String>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -243,6 +243,7 @@ fn main() {
|
||||
```
|
||||
*/
|
||||
|
||||
use std::mem;
|
||||
pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress};
|
||||
|
||||
/// An owning reference.
|
||||
@ -279,7 +280,7 @@ pub struct OwningRefMut<O, T: ?Sized> {
|
||||
pub trait Erased {}
|
||||
impl<T> Erased for T {}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner derferences to,
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErased<'a> {
|
||||
@ -289,10 +290,20 @@ pub unsafe trait IntoErased<'a> {
|
||||
fn into_erased(self) -> Self::Erased;
|
||||
}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner derferences to,
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased + Send>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErasedSend<'a> {
|
||||
/// Owner with the dereference type substituted to `Erased + Send`.
|
||||
type Erased: Send;
|
||||
/// Perform the type erasure.
|
||||
fn into_erased_send(self) -> Self::Erased;
|
||||
}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased + Send + Sync>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErasedSendSync<'a>: Send + Sync {
|
||||
pub unsafe trait IntoErasedSendSync<'a> {
|
||||
/// Owner with the dereference type substituted to `Erased + Send + Sync`.
|
||||
type Erased: Send + Sync;
|
||||
/// Perform the type erasure.
|
||||
@ -472,6 +483,18 @@ pub fn erase_owner<'a>(self) -> OwningRef<O::Erased, T>
|
||||
}
|
||||
}
|
||||
|
||||
/// Erases the concrete base type of the owner with a trait object which implements `Send`.
|
||||
///
|
||||
/// This allows mixing of owned references with different owner base types.
|
||||
pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T>
|
||||
where O: IntoErasedSend<'a>,
|
||||
{
|
||||
OwningRef {
|
||||
reference: self.reference,
|
||||
owner: self.owner.into_erased_send(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`.
|
||||
///
|
||||
/// This allows mixing of owned references with different owner base types.
|
||||
@ -1161,13 +1184,25 @@ fn into_erased(self) -> Self::Erased {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Send + Sync + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Send + 'a>;
|
||||
fn into_erased_send(self) -> Self::Erased {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Sync + Send + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
let result: Box<Erased + Send + 'a> = self;
|
||||
// This is safe since Erased can always implement Sync
|
||||
// Only the destructor is available and it takes &mut self
|
||||
unsafe {
|
||||
mem::transmute(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> {
|
||||
type Erased = Arc<Erased + Send + Sync + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
|
@ -177,7 +177,7 @@ pub fn take(&self) -> Option<T> {
|
||||
macro_rules! rustc_erase_owner {
|
||||
($v:expr) => {{
|
||||
let v = $v;
|
||||
::rustc_data_structures::sync::assert_send_sync_val(&v);
|
||||
::rustc_data_structures::sync::assert_send_val(&v);
|
||||
v.erase_send_sync_owner()
|
||||
}}
|
||||
}
|
||||
@ -262,6 +262,7 @@ fn clone(&self) -> Self {
|
||||
}
|
||||
|
||||
pub fn assert_sync<T: ?Sized + Sync>() {}
|
||||
pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
|
||||
pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -22,6 +22,8 @@ pub struct ArchiveRO {
|
||||
ptr: ArchiveRef,
|
||||
}
|
||||
|
||||
unsafe impl Send for ArchiveRO {}
|
||||
|
||||
pub struct Iter<'a> {
|
||||
archive: &'a ArchiveRO,
|
||||
ptr: ::ArchiveIteratorRef,
|
||||
|
@ -221,6 +221,8 @@ pub struct ObjectFile {
|
||||
pub llof: ObjectFileRef,
|
||||
}
|
||||
|
||||
unsafe impl Send for ObjectFile {}
|
||||
|
||||
impl ObjectFile {
|
||||
// This will take ownership of llmb
|
||||
pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::owning_ref::ErasedBoxRef;
|
||||
use syntax::{ast, attr};
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
@ -42,7 +41,9 @@
|
||||
// own crate numbers.
|
||||
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
|
||||
|
||||
pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub struct MetadataBlob(pub MetadataRef);
|
||||
|
||||
/// Holds information about a syntax_pos::FileMap imported from another crate.
|
||||
/// See `imported_filemaps()` for more information.
|
||||
|
@ -39,6 +39,7 @@
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
#[macro_use]
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
mod diagnostics;
|
||||
|
@ -219,7 +219,7 @@
|
||||
//! no means all of the necessary details. Take a look at the rest of
|
||||
//! metadata::locator or metadata::creader for all the juicy details!
|
||||
|
||||
use cstore::MetadataBlob;
|
||||
use cstore::{MetadataRef, MetadataBlob};
|
||||
use creader::Library;
|
||||
use schema::{METADATA_HEADER, rustc_version};
|
||||
|
||||
@ -243,8 +243,8 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use flate2::read::DeflateDecoder;
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
pub struct CrateMismatch {
|
||||
path: PathBuf,
|
||||
got: String,
|
||||
@ -842,7 +842,7 @@ fn get_metadata_section_imp(target: &Target,
|
||||
if !filename.exists() {
|
||||
return Err(format!("no such file: '{}'", filename.display()));
|
||||
}
|
||||
let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
|
||||
let raw_bytes: MetadataRef = match flavor {
|
||||
CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
|
||||
CrateFlavor::Dylib => {
|
||||
let buf = loader.get_dylib_metadata(target, filename)?;
|
||||
@ -862,7 +862,7 @@ fn get_metadata_section_imp(target: &Target,
|
||||
match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
|
||||
Ok(_) => {
|
||||
let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
|
||||
buf.map_owner_box().erase_owner()
|
||||
rustc_erase_owner!(buf.map_owner_box())
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(format!("failed to decompress metadata: {}", filename.display()));
|
||||
@ -872,7 +872,7 @@ fn get_metadata_section_imp(target: &Target,
|
||||
CrateFlavor::Rmeta => {
|
||||
let buf = fs::read(filename).map_err(|_|
|
||||
format!("failed to read rmeta metadata: '{}'", filename.display()))?;
|
||||
OwningRef::new(buf).map_owner_box().erase_owner()
|
||||
rustc_erase_owner!(OwningRef::new(buf).map_owner_box())
|
||||
}
|
||||
};
|
||||
let blob = MetadataBlob(raw_bytes);
|
||||
|
@ -51,7 +51,7 @@
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_binaryen;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_data_structures;
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
extern crate rustc_demangle;
|
||||
extern crate rustc_incremental;
|
||||
extern crate rustc_llvm as llvm;
|
||||
|
@ -15,17 +15,19 @@
|
||||
use llvm::{False, ObjectFile, mk_section_iter};
|
||||
use llvm::archive_ro::ArchiveRO;
|
||||
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub const METADATA_FILENAME: &str = "rust.metadata.bin";
|
||||
|
||||
pub struct LlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoader for LlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
|
||||
// internally to read the file. We also avoid even using a memcpy by
|
||||
// just keeping the archive along while the metadata is in use.
|
||||
@ -47,13 +49,13 @@ fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<
|
||||
filename.display())
|
||||
})
|
||||
})?;
|
||||
Ok(buf.erase_owner())
|
||||
Ok(rustc_erase_owner!(buf))
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String> {
|
||||
-> Result<MetadataRef, String> {
|
||||
unsafe {
|
||||
let buf = common::path2cstr(filename);
|
||||
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
||||
@ -65,7 +67,7 @@ fn get_dylib_metadata(&self,
|
||||
.ok_or_else(|| format!("provided path not an object file: '{}'",
|
||||
filename.display()))?;
|
||||
let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
|
||||
Ok(buf.erase_owner())
|
||||
Ok(rustc_erase_owner!(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
extern crate rustc_data_structures;
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
|
||||
pub extern crate rustc as __rustc;
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use ar::{Archive, Builder, Header};
|
||||
use flate2::Compression;
|
||||
@ -47,6 +47,8 @@
|
||||
use rustc_mir::monomorphize::collector;
|
||||
use link::{build_link_meta, out_filename};
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub trait TransCrate {
|
||||
fn init(&self, _sess: &Session) {}
|
||||
fn print(&self, _req: PrintRequest, _sess: &Session) {}
|
||||
@ -119,7 +121,7 @@ fn get_rlib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
bug!("DummyMetadataLoader::get_rlib_metadata");
|
||||
}
|
||||
|
||||
@ -127,7 +129,7 @@ fn get_dylib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
bug!("DummyMetadataLoader::get_dylib_metadata");
|
||||
}
|
||||
}
|
||||
@ -135,7 +137,7 @@ fn get_dylib_metadata(
|
||||
pub struct NoLlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoader for NoLlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||
let file = File::open(filename)
|
||||
.map_err(|e| format!("metadata file open err: {:?}", e))?;
|
||||
let mut archive = Archive::new(file);
|
||||
@ -147,7 +149,7 @@ fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<
|
||||
let mut buf = Vec::new();
|
||||
io::copy(&mut entry, &mut buf).unwrap();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
return Ok(buf.map_owner_box().erase_owner());
|
||||
return Ok(rustc_erase_owner!(buf.map_owner_box()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +160,7 @@ fn get_dylib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path,
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
// FIXME: Support reading dylibs from llvm enabled rustc
|
||||
self.get_rlib_metadata(_target, _filename)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user