Make metadata references Send + Sync

This commit is contained in:
John Kåre Alsaker 2018-03-03 06:17:06 +01:00
parent e8af0f4c1f
commit 62089c335f
12 changed files with 76 additions and 31 deletions

View File

@ -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)]

View File

@ -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 {

View File

@ -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]

View File

@ -22,6 +22,8 @@ pub struct ArchiveRO {
ptr: ArchiveRef,
}
unsafe impl Send for ArchiveRO {}
pub struct Iter<'a> {
archive: &'a ArchiveRO,
ptr: ::ArchiveIteratorRef,

View File

@ -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> {

View File

@ -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.

View File

@ -39,6 +39,7 @@
#[macro_use]
extern crate rustc;
extern crate rustc_back;
#[macro_use]
extern crate rustc_data_structures;
mod diagnostics;

View File

@ -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);

View File

@ -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;

View File

@ -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))
}
}
}

View File

@ -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;

View File

@ -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)
}