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

Rollup of 8 pull requests #59632

Merged
merged 22 commits into from
Apr 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
079d9b1
Forward Iterator::{ne, lt, le, gt, ge} to Iterator::{eq, partial_cmp}
timvermeulen Mar 17, 2019
6778396
Add iter::{bench_partial_cmp, bench_lt} benchmarks
timvermeulen Mar 17, 2019
075b269
Simplify Iterator::{lt, gt}
timvermeulen Mar 18, 2019
01162d8
Implement useful steps_between for all integers
cuviper Mar 26, 2019
3d389f2
Test the size_hint of empty ranges too
cuviper Mar 26, 2019
a548d83
impl TrustedLen for 128-bit ranges too
cuviper Mar 26, 2019
7f2c726
Speed up rustdoc run a bit
GuillaumeGomez Mar 26, 2019
16ee042
Fixes for shallow borrows
matthewjasper Mar 31, 2019
3c8caac
renames EvalErrorKind to InterpError
kenta7777 Apr 1, 2019
6d96c89
SGX target: convert a bunch of panics to aborts
Feb 17, 2019
30e7e9c
Support allocating iterators with arenas
Zoxc Dec 14, 2018
e8b3aea
Use set_len
Zoxc Apr 1, 2019
59ff059
Add ensure_capacity and rename min to len
Zoxc Apr 1, 2019
749349f
Refactor async fn return type lowering
cramertj Mar 14, 2019
c9d9df5
Rollup merge of #59262 - timvermeulen:iterator_cmp_dedup, r=scottmcm
Centril Apr 2, 2019
d86a8f3
Rollup merge of #59286 - cramertj:async-fn-ret-ty, r=varkor
Centril Apr 2, 2019
5e8998a
Rollup merge of #59444 - cuviper:steps_between, r=scottmcm
Centril Apr 2, 2019
e655b91
Rollup merge of #59452 - GuillaumeGomez:speedup-rustdoc, r=QuietMisdr…
Centril Apr 2, 2019
274f80e
Rollup merge of #59533 - Zoxc:arena-slices, r=michaelwoerister
Centril Apr 2, 2019
69bc687
Rollup merge of #59585 - rust-lang:shallow-borrow-fixes, r=pnkfelix
Centril Apr 2, 2019
85a82ac
Rollup merge of #59607 - kenta7777:renames-EvalErrorKind-to-InterpErr…
Centril Apr 2, 2019
d0d3466
Rollup merge of #59613 - jethrogb:jb/waitqueue-wait-unwind, r=alexcri…
Centril Apr 2, 2019
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: 4 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ name = "arena"
version = "0.0.0"
dependencies = [
"rustc_data_structures 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
Expand Down Expand Up @@ -1520,7 +1521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "minifier"
version = "0.0.28"
version = "0.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
Expand Down Expand Up @@ -3039,7 +3040,7 @@ dependencies = [
name = "rustdoc"
version = "0.0.0"
dependencies = [
"minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
Expand Down Expand Up @@ -4149,7 +4150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2898502751dcc9d66b6fff57f3cf63cc91605e83e1a33515396f5027f8e4ca"
"checksum minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4950cb2617b1933e2da0446e864dfe0d6a22c22ff72297996c46e6a63b210b"
"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
Expand Down
1 change: 1 addition & 0 deletions src/libarena/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ crate-type = ["dylib"]

[dependencies]
rustc_data_structures = { path = "../librustc_data_structures" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
155 changes: 139 additions & 16 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@

extern crate alloc;

use rustc_data_structures::cold_path;
use rustc_data_structures::sync::MTLock;
use smallvec::SmallVec;

use std::cell::{Cell, RefCell};
use std::cmp;
Expand Down Expand Up @@ -55,13 +57,16 @@ pub struct TypedArena<T> {
struct TypedArenaChunk<T> {
/// The raw storage for the arena chunk.
storage: RawVec<T>,
/// The number of valid entries in the chunk.
entries: usize,
}

impl<T> TypedArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
TypedArenaChunk {
storage: RawVec::with_capacity(capacity),
entries: 0,
}
}

Expand Down Expand Up @@ -149,6 +154,34 @@ impl<T> TypedArena<T> {
}
}

#[inline]
fn can_allocate(&self, len: usize) -> bool {
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
let at_least_bytes = len.checked_mul(mem::size_of::<T>()).unwrap();
available_capacity_bytes >= at_least_bytes
}

/// Ensures there's enough space in the current chunk to fit `len` objects.
#[inline]
fn ensure_capacity(&self, len: usize) {
if !self.can_allocate(len) {
self.grow(len);
debug_assert!(self.can_allocate(len));
}
}

#[inline]
unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
assert!(mem::size_of::<T>() != 0);
assert!(len != 0);

self.ensure_capacity(len);

let start_ptr = self.ptr.get();
self.ptr.set(start_ptr.add(len));
start_ptr
}

/// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
/// reference to it. Will panic if passed a zero-sized types.
///
Expand All @@ -161,21 +194,64 @@ impl<T> TypedArena<T> {
where
T: Copy,
{
unsafe {
let len = slice.len();
let start_ptr = self.alloc_raw_slice(len);
slice.as_ptr().copy_to_nonoverlapping(start_ptr, len);
slice::from_raw_parts_mut(start_ptr, len)
}
}

#[inline]
pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
let mut iter = iter.into_iter();
let size_hint = iter.size_hint();

let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
let at_least_bytes = slice.len() * mem::size_of::<T>();
if available_capacity_bytes < at_least_bytes {
self.grow(slice.len());
}
match size_hint {
(min, Some(max)) if min == max => {
// We know the exact number of elements the iterator will produce here
let len = min;

unsafe {
let start_ptr = self.ptr.get();
let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
self.ptr.set(start_ptr.add(arena_slice.len()));
arena_slice.copy_from_slice(slice);
arena_slice
if len == 0 {
return &mut [];
}

self.ensure_capacity(len);

let slice = self.ptr.get();

unsafe {
let mut ptr = self.ptr.get();
for _ in 0..len {
// Write into uninitialized memory.
ptr::write(ptr, iter.next().unwrap());
// Advance the pointer.
ptr = ptr.offset(1);
// Update the pointer per iteration so if `iter.next()` panics
// we destroy the correct amount
self.ptr.set(ptr);
}
slice::from_raw_parts_mut(slice, len)
}
}
_ => {
cold_path(move || -> &mut [T] {
let mut vec: SmallVec<[_; 8]> = iter.collect();
if vec.is_empty() {
return &mut [];
}
// Move the content to the arena by copying it and then forgetting
// the content of the SmallVec
unsafe {
let len = vec.len();
let start_ptr = self.alloc_raw_slice(len);
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
vec.set_len(0);
slice::from_raw_parts_mut(start_ptr, len)
}
})
}
}
}

Expand All @@ -189,6 +265,7 @@ impl<T> TypedArena<T> {
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
let currently_used_cap = used_bytes / mem::size_of::<T>();
last_chunk.entries = currently_used_cap;
if last_chunk.storage.reserve_in_place(currently_used_cap, n) {
self.end.set(last_chunk.end());
return;
Expand Down Expand Up @@ -222,8 +299,7 @@ impl<T> TypedArena<T> {
let len = chunks_borrow.len();
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..len-1) {
let cap = chunk.storage.cap();
chunk.destroy(cap);
chunk.destroy(chunk.entries);
}
}
}
Expand Down Expand Up @@ -265,8 +341,7 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.cap();
chunk.destroy(cap);
chunk.destroy(chunk.entries);
}
}
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
Expand Down Expand Up @@ -410,6 +485,54 @@ impl DroplessArena {
arena_slice
}
}

#[inline]
pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
let mut iter = iter.into_iter();
assert!(mem::size_of::<T>() != 0);
assert!(!mem::needs_drop::<T>());

let size_hint = iter.size_hint();

match size_hint {
(min, Some(max)) if min == max => {
// We know the exact number of elements the iterator will produce here
let len = min;

if len == 0 {
return &mut []
}
let size = len.checked_mul(mem::size_of::<T>()).unwrap();
let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T;
unsafe {
for i in 0..len {
ptr::write(mem.offset(i as isize), iter.next().unwrap())
}
slice::from_raw_parts_mut(mem, len)
}
}
(_, _) => {
cold_path(move || -> &mut [T] {
let mut vec: SmallVec<[_; 8]> = iter.collect();
if vec.is_empty() {
return &mut [];
}
// Move the content to the arena by copying it and then forgetting
// the content of the SmallVec
unsafe {
let len = vec.len();
let start_ptr = self.alloc_raw(
len * mem::size_of::<T>(),
mem::align_of::<T>()
) as *mut _ as *mut T;
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
vec.set_len(0);
slice::from_raw_parts_mut(start_ptr, len)
}
})
}
}
}
}

#[derive(Default)]
Expand Down
10 changes: 10 additions & 0 deletions src/libcore/benches/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,13 @@ fn bench_filter_chain_ref_count(b: &mut Bencher) {
(0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
})
}

#[bench]
fn bench_partial_cmp(b: &mut Bencher) {
b.iter(|| (0..100000).map(black_box).partial_cmp((0..100000).map(black_box)))
}

#[bench]
fn bench_lt(b: &mut Bencher) {
b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box)))
}
61 changes: 10 additions & 51 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,9 @@ macro_rules! step_impl_unsigned {
issue = "42168")]
impl Step for $t {
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t) -> Option<usize> {
if *start < *end {
// Note: We assume $t <= usize here
Some((*end - *start) as usize)
usize::try_from(*end - *start).ok()
} else {
Some(0)
}
Expand All @@ -98,13 +96,11 @@ macro_rules! step_impl_signed {
issue = "42168")]
impl Step for $t {
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t) -> Option<usize> {
if *start < *end {
// Note: We assume $t <= isize here
// Use .wrapping_sub and cast to usize to compute the
// difference that may not fit inside the range of isize.
Some((*end as isize).wrapping_sub(*start as isize) as usize)
// Use .wrapping_sub and cast to unsigned to compute the
// difference that may not fit inside the range of $t.
usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
} else {
Some(0)
}
Expand Down Expand Up @@ -134,46 +130,9 @@ macro_rules! step_impl_signed {
)*)
}

macro_rules! step_impl_no_between {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
issue = "42168")]
impl Step for $t {
#[inline]
fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
None
}

#[inline]
fn add_usize(&self, n: usize) -> Option<Self> {
self.checked_add(n as $t)
}

step_identical_methods!();
}
)*)
}

step_impl_unsigned!(usize u8 u16);
#[cfg(not(target_pointer_width = "16"))]
step_impl_unsigned!(u32);
#[cfg(target_pointer_width = "16")]
step_impl_no_between!(u32);
step_impl_unsigned!(usize u8 u16 u32 u64 u128);
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
#[cfg(not(target_pointer_width = "16"))]
step_impl_signed!([i32: u32]);
#[cfg(target_pointer_width = "16")]
step_impl_no_between!(i32);
#[cfg(target_pointer_width = "64")]
step_impl_unsigned!(u64);
#[cfg(target_pointer_width = "64")]
step_impl_signed!([i64: u64]);
// If the target pointer width is not 64-bits, we
// assume here that it is less than 64-bits.
#[cfg(not(target_pointer_width = "64"))]
step_impl_no_between!(u64 i64);
step_impl_no_between!(u128 i128);
step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);

macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
Expand Down Expand Up @@ -229,7 +188,7 @@ impl<A: Step> Iterator for ops::Range<A> {
fn size_hint(&self) -> (usize, Option<usize>) {
match Step::steps_between(&self.start, &self.end) {
Some(hint) => (hint, Some(hint)),
None => (0, None)
None => (usize::MAX, None)
}
}

Expand Down Expand Up @@ -273,8 +232,8 @@ range_incl_exact_iter_impl!(u8 u16 i8 i16);
//
// They need to guarantee that .size_hint() is either exact, or that
// the upper bound is None when it does not fit the type limits.
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
Expand Down Expand Up @@ -350,7 +309,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {

match Step::steps_between(&self.start, &self.end) {
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
None => (0, None),
None => (usize::MAX, None),
}
}

Expand Down
Loading