Skip to content

Commit

Permalink
Make metadata references Send + Sync
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Mar 7, 2018
1 parent e8af0f4 commit 62089c3
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 31 deletions.
7 changes: 3 additions & 4 deletions src/librustc/middle/cstore.rs
Expand Up @@ -37,13 +37,12 @@ use util::nodemap::NodeSet;
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::*;

Expand Down Expand Up @@ -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)]
Expand Down
47 changes: 41 additions & 6 deletions src/librustc_data_structures/owning_ref/mod.rs
Expand Up @@ -243,6 +243,7 @@ fn main() {
```
*/

use std::mem;
pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress};

/// An owning reference.
Expand Down Expand Up @@ -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> {
Expand All @@ -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.
Expand Down Expand Up @@ -472,6 +483,18 @@ impl<O, T: ?Sized> OwningRef<O, 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.
Expand Down Expand Up @@ -1161,13 +1184,25 @@ unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> {
}
}

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 {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_data_structures/sync.rs
Expand Up @@ -177,7 +177,7 @@ cfg_if! {
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()
}}
}
Expand Down Expand Up @@ -262,6 +262,7 @@ cfg_if! {
}

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]
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_llvm/archive_ro.rs
Expand Up @@ -22,6 +22,8 @@ pub struct ArchiveRO {
ptr: ArchiveRef,
}

unsafe impl Send for ArchiveRO {}

pub struct Iter<'a> {
archive: &'a ArchiveRO,
ptr: ::ArchiveIteratorRef,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_llvm/lib.rs
Expand Up @@ -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> {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_metadata/cstore.rs
Expand Up @@ -24,7 +24,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};

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;
Expand All @@ -42,7 +41,9 @@ pub use cstore_impl::{provide, provide_extern};
// 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.
Expand Down
1 change: 1 addition & 0 deletions src/librustc_metadata/lib.rs
Expand Up @@ -39,6 +39,7 @@ extern crate proc_macro;
#[macro_use]
extern crate rustc;
extern crate rustc_back;
#[macro_use]
extern crate rustc_data_structures;

mod diagnostics;
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_metadata/locator.rs
Expand Up @@ -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};

Expand All @@ -243,8 +243,8 @@ use std::path::{Path, PathBuf};
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,
Expand Down Expand Up @@ -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)?;
Expand All @@ -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()));
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/lib.rs
Expand Up @@ -51,7 +51,7 @@ extern crate rustc_apfloat;
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;
Expand Down
12 changes: 7 additions & 5 deletions src/librustc_trans/metadata.rs
Expand Up @@ -15,17 +15,19 @@ use llvm;
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.
Expand All @@ -47,13 +49,13 @@ impl MetadataLoader for LlvmMetadataLoader {
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());
Expand All @@ -65,7 +67,7 @@ impl MetadataLoader for LlvmMetadataLoader {
.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))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans_utils/lib.rs
Expand Up @@ -40,7 +40,7 @@ extern crate rustc_incremental;
#[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;

Expand Down
14 changes: 8 additions & 6 deletions src/librustc_trans_utils/trans_crate.rs
Expand Up @@ -28,7 +28,7 @@ use std::fs::File;
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;
Expand All @@ -47,6 +47,8 @@ use rustc_back::target::Target;
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) {}
Expand Down Expand Up @@ -119,23 +121,23 @@ impl MetadataLoader for DummyMetadataLoader {
&self,
_target: &Target,
_filename: &Path
) -> Result<ErasedBoxRef<[u8]>, String> {
) -> Result<MetadataRef, String> {
bug!("DummyMetadataLoader::get_rlib_metadata");
}

fn get_dylib_metadata(
&self,
_target: &Target,
_filename: &Path
) -> Result<ErasedBoxRef<[u8]>, String> {
) -> Result<MetadataRef, String> {
bug!("DummyMetadataLoader::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);
Expand All @@ -147,7 +149,7 @@ impl MetadataLoader for NoLlvmMetadataLoader {
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()));
}
}

Expand All @@ -158,7 +160,7 @@ impl MetadataLoader for NoLlvmMetadataLoader {
&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)
}
Expand Down

0 comments on commit 62089c3

Please sign in to comment.