Skip to content

Commit b20534f

Browse files
CoAlloc: Undoing generalizations + splitting. WIP
1 parent 6afb0d6 commit b20534f

File tree

5 files changed

+130
-16
lines changed

5 files changed

+130
-16
lines changed

library/alloc/src/boxed.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2051,7 +2051,7 @@ where
20512051
fn clone(&self) -> Self {
20522052
let alloc = Box::allocator(self).clone();
20532053
// false = no need for co-alloc metadata, since it would get lost once converted to the boxed slice.
2054-
self.to_vec_in::<A, {CO_ALLOC_PREF_META_NO!()}>(alloc).into_boxed_slice()
2054+
self.to_vec_in_co::<A, {CO_ALLOC_PREF_META_NO!()}>(alloc).into_boxed_slice()
20552055
}
20562056

20572057
fn clone_from(&mut self, other: &Self) {

library/alloc/src/slice.rs

Lines changed: 124 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,44 @@ pub(crate) mod hack {
114114
#[cfg(not(no_global_oom_handling))]
115115
#[inline]
116116
#[allow(unused_braces)]
117-
pub fn to_vec<T: ConvertVec, A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
117+
pub fn to_vec<T: ConvertVec, A: Allocator>(
118+
s: &[T],
119+
alloc: A,
120+
) -> Vec<T, A>
121+
where
122+
[(); {crate::meta_num_slots_default!(A)}]:,
123+
{
124+
T::to_vec(s, alloc)
125+
}
126+
127+
#[cfg(not(no_global_oom_handling))]
128+
#[inline]
129+
#[allow(unused_braces)]
130+
pub fn to_vec_co<T: ConvertVecCo, A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
118131
s: &[T],
119132
alloc: A,
120133
) -> Vec<T, A, CO_ALLOC_PREF>
121134
where
122135
[(); {crate::meta_num_slots!(A, CO_ALLOC_PREF)}]:,
123136
{
124-
T::to_vec(s, alloc)
137+
T::to_vec_co(s, alloc)
125138
}
126139

127140
#[cfg(not(no_global_oom_handling))]
128141
#[allow(unused_braces)]
129142
pub trait ConvertVec {
130-
fn to_vec<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
143+
fn to_vec<A: Allocator>(
144+
s: &[Self],
145+
alloc: A,
146+
) -> Vec<Self, A>
147+
where
148+
Self: Sized,
149+
[(); {crate::meta_num_slots_default!(A)}]:;
150+
}
151+
152+
#[allow(unused_braces)]
153+
pub trait ConvertVecCo {
154+
fn to_vec_co<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
131155
s: &[Self],
132156
alloc: A,
133157
) -> Vec<Self, A, CO_ALLOC_PREF>
@@ -141,7 +165,82 @@ pub(crate) mod hack {
141165
impl<T: Clone> ConvertVec for T {
142166
#[inline]
143167
#[allow(unused_braces)]
144-
default fn to_vec<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
168+
default fn to_vec<A: Allocator>(
169+
s: &[Self],
170+
alloc: A,
171+
) -> Vec<Self, A>
172+
where
173+
[(); {crate::meta_num_slots_default!(A)}]:,
174+
{
175+
#[allow(unused_braces)]
176+
struct DropGuard<'a, T, A: Allocator>
177+
where
178+
[(); {crate::meta_num_slots_default!(A)}]:,
179+
{
180+
vec: &'a mut Vec<T, A>,
181+
num_init: usize,
182+
}
183+
impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A>
184+
where
185+
[(); {crate::meta_num_slots_default!(A)}]:,
186+
{
187+
#[inline]
188+
fn drop(&mut self) {
189+
// SAFETY:
190+
// items were marked initialized in the loop below
191+
unsafe {
192+
self.vec.set_len(self.num_init);
193+
}
194+
}
195+
}
196+
let mut vec = Vec::with_capacity_in(s.len(), alloc);
197+
let mut guard = DropGuard { vec: &mut vec, num_init: 0 };
198+
let slots = guard.vec.spare_capacity_mut();
199+
// .take(slots.len()) is necessary for LLVM to remove bounds checks
200+
// and has better codegen than zip.
201+
for (i, b) in s.iter().enumerate().take(slots.len()) {
202+
guard.num_init = i;
203+
slots[i].write(b.clone());
204+
}
205+
core::mem::forget(guard);
206+
// SAFETY:
207+
// the vec was allocated and initialized above to at least this length.
208+
unsafe {
209+
vec.set_len(s.len());
210+
}
211+
vec
212+
}
213+
}
214+
215+
#[cfg(not(no_global_oom_handling))]
216+
impl<T: Copy> ConvertVec for T {
217+
#[inline]
218+
#[allow(unused_braces)]
219+
fn to_vec<A: Allocator>(
220+
s: &[Self],
221+
alloc: A,
222+
) -> Vec<Self, A>
223+
where
224+
[(); {crate::meta_num_slots_default!(A)}]:,
225+
{
226+
let mut v = Vec::with_capacity_in(s.len(), alloc);
227+
// SAFETY:
228+
// allocated above with the capacity of `s`, and initialize to `s.len()` in
229+
// ptr::copy_to_non_overlapping below.
230+
unsafe {
231+
s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
232+
v.set_len(s.len());
233+
}
234+
v
235+
}
236+
}
237+
238+
#[cfg(not(no_global_oom_handling))]
239+
#[allow(unused_braces)]
240+
impl<T: Clone> ConvertVecCo for T {
241+
#[inline]
242+
#[allow(unused_braces)]
243+
default fn to_vec_co<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
145244
s: &[Self],
146245
alloc: A,
147246
) -> Vec<Self, A, CO_ALLOC_PREF>
@@ -189,10 +288,10 @@ pub(crate) mod hack {
189288
}
190289

191290
#[cfg(not(no_global_oom_handling))]
192-
impl<T: Copy> ConvertVec for T {
291+
impl<T: Copy> ConvertVecCo for T {
193292
#[inline]
194293
#[allow(unused_braces)]
195-
fn to_vec<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
294+
fn to_vec_co<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(
196295
s: &[Self],
197296
alloc: A,
198297
) -> Vec<Self, A, CO_ALLOC_PREF>
@@ -209,8 +308,7 @@ pub(crate) mod hack {
209308
}
210309
v
211310
}
212-
}
213-
}
311+
}}
214312

215313
#[cfg(not(test))]
216314
impl<T> [T] {
@@ -455,7 +553,7 @@ impl<T> [T] {
455553
T: Clone,
456554
[(); {meta_num_slots_global!(CO_ALLOC_PREF)}]:,
457555
{
458-
self.to_vec_in::<Global, CO_ALLOC_PREF>(Global)
556+
self.to_vec_in_co::<Global, CO_ALLOC_PREF>(Global)
459557
}
460558

461559
/// Copies `self` into a new `Vec` with an allocator.
@@ -476,15 +574,30 @@ impl<T> [T] {
476574
#[inline]
477575
#[unstable(feature = "allocator_api", issue = "32838")]
478576
#[allow(unused_braces)]
479-
pub fn to_vec_in<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(&self, alloc: A) -> Vec<T, A, CO_ALLOC_PREF>
577+
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
480578
where
481579
T: Clone,
482-
[(); {crate::meta_num_slots!(A, CO_ALLOC_PREF)}]:,
580+
[(); {crate::meta_num_slots_default!(A)}]:,
483581
{
484582
// N.B., see the `hack` module in this file for more details.
485583
hack::to_vec(self, alloc)
486584
}
487585

586+
/// Coallocation-aware version of `to_vec_in`.
587+
#[cfg(not(no_global_oom_handling))]
588+
#[rustc_allow_incoherent_impl]
589+
#[inline]
590+
#[unstable(feature = "allocator_api", issue = "32838")]
591+
#[allow(unused_braces)]
592+
pub fn to_vec_in_co<A: Allocator, const CO_ALLOC_PREF: CoAllocPref>(&self, alloc: A) -> Vec<T, A, CO_ALLOC_PREF>
593+
where
594+
T: Clone,
595+
[(); {crate::meta_num_slots!(A, CO_ALLOC_PREF)}]:,
596+
{
597+
// N.B., see the `hack` module in this file for more details.
598+
hack::to_vec_co(self, alloc)
599+
}
600+
488601
/// Converts `self` into a vector without clones or allocation.
489602
///
490603
/// The resulting vector can be converted back into a box via

library/alloc/src/vec/into_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ where
439439
// @FIXME Remove the following extras - used for type checks only
440440
let slice = self.as_slice();
441441
let vec: crate::vec::Vec<T, A, CO_ALLOC_PREF> =
442-
slice.to_vec_in::<A, CO_ALLOC_PREF>(self.alloc.deref().clone());
442+
slice.to_vec_in_co::<A, CO_ALLOC_PREF>(self.alloc.deref().clone());
443443
let _iter: IntoIter<T, A, CO_ALLOC_PREF> = vec.into_iter();
444444

445445
//self.as_slice().to_vec_in::<A, CO_ALLOC_PREF>(self.alloc.deref().clone()).into_iter()

library/alloc/src/vec/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2826,7 +2826,7 @@ where
28262826
#[cfg(not(test))]
28272827
fn clone(&self) -> Self {
28282828
let alloc = self.allocator().clone();
2829-
<[T]>::to_vec_in(&**self, alloc)
2829+
<[T]>::to_vec_in_co(&**self, alloc)
28302830
}
28312831

28322832
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is

library/test/src/stats.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(missing_docs)]
22

33
use std::mem;
4+
use std::SHORT_TERM_VEC_CO_ALLOC_PREF;
45

56
#[cfg(test)]
67
mod tests;
@@ -232,13 +233,13 @@ impl Stats for [f64] {
232233
}
233234

234235
fn percentile(&self, pct: f64) -> f64 {
235-
let mut tmp = self.to_vec::<{std::SHORT_TERM_VEC_CO_ALLOC_PREF!()}>();
236+
let mut tmp = self.to_vec_co::<{SHORT_TERM_VEC_CO_ALLOC_PREF!()}>();
236237
local_sort(&mut tmp);
237238
percentile_of_sorted(&tmp, pct)
238239
}
239240

240241
fn quartiles(&self) -> (f64, f64, f64) {
241-
let mut tmp = self.to_vec();
242+
let mut tmp = self.to_vec_co::<{SHORT_TERM_VEC_CO_ALLOC_PREF!()}>();
242243
local_sort(&mut tmp);
243244
let first = 25_f64;
244245
let a = percentile_of_sorted(&tmp, first);

0 commit comments

Comments
 (0)