Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make metadata references Send + Sync #48690

Merged
merged 1 commit into from
Mar 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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