Skip to content

Commit

Permalink
CoAlloc (big squash)
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-lyons-kehl committed Dec 5, 2023
1 parent da1da3f commit ad541b4
Show file tree
Hide file tree
Showing 83 changed files with 2,749 additions and 454 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#![feature(dropck_eyepatch)]
#![feature(new_uninit)]
#![feature(maybe_uninit_slice)]
#![feature(min_specialization)]
// FIXME CoAlloc needs min_specialization at all!?
#![feature(decl_macro)]
#![feature(rustc_attrs)]
#![cfg_attr(test, feature(test))]
Expand Down
24 changes: 12 additions & 12 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub use rustc_type_ir::{Movability, Mutability};
use std::fmt;
use std::mem;
use thin_vec::{thin_vec, ThinVec};

/// A "Label" is an identifier of some point in sources,
/// e.g. in the following code:
///
Expand Down Expand Up @@ -3170,30 +3169,31 @@ pub type ForeignItem = Item<ForeignItemKind>;
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
use std::alloc::{Allocator, Global};
// tidy-alphabetical-start
static_assert_size!(AssocItem, 88);
static_assert_size!(AssocItemKind, 16);
static_assert_size!(Attribute, 32);
static_assert_size!(Block, 32);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
static_assert_size!(Fn, 152);
static_assert_size!(Block, 32 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Expr, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(ExprKind, 40 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Fn, 152 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
static_assert_size!(GenericArg, 24);
static_assert_size!(GenericBound, 64);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 136);
static_assert_size!(Item, 136);
static_assert_size!(ItemKind, 64);
static_assert_size!(GenericBound, 64 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Generics, 40 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Impl, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Item, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(ItemKind, 64 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 72);
static_assert_size!(Pat, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Path, 24);
static_assert_size!(PathSegment, 24);
static_assert_size!(PatKind, 48);
static_assert_size!(PatKind, 48 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 64);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
#![doc(rust_logo)]
#![allow(internal_features)]
#![feature(rustdoc_internals)]
#![feature(allocator_api)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(const_trait_impl)]
#![feature(global_co_alloc_meta)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(min_specialization)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None; // do not suggest code that is already there (#53348)
}

let method_call_list = [sym::to_vec, sym::to_string];
let method_call_list = [sym::to_vec, sym::to_vec_co, sym::to_string];
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
&& receiver_method.ident.name == sym::clone
&& method_call_list.contains(&conversion_method.name)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#![feature(exhaustive_patterns)]
#![feature(coroutines)]
#![feature(get_mut_unchecked)]
#![feature(global_co_alloc_meta)]
#![feature(if_let_guard)]
#![feature(inline_const)]
#![feature(iter_from_coroutine)]
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1651,7 +1651,10 @@ mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 136);
static_assert_size!(
BasicBlockData<'_>,
136 + mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
);
static_assert_size!(LocalDecl<'_>, 40);
static_assert_size!(SourceScopeData<'_>, 72);
static_assert_size!(Statement<'_>, 32);
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,9 @@ mod size_asserts {
static_assert_size!(Operand<'_>, 24);
static_assert_size!(Place<'_>, 16);
static_assert_size!(PlaceElem<'_>, 24);
static_assert_size!(Rvalue<'_>, 40);
static_assert_size!(
Rvalue<'_>,
40 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
);
// tidy-alphabetical-end
}
2 changes: 2 additions & 0 deletions compiler/rustc_parse/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! The main parser interface.

#![feature(allocator_api)]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(global_co_alloc_meta)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_parse/src/parser/attr_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,12 @@ fn make_token_stream(
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
use std::alloc::{Allocator, Global};
// tidy-alphabetical-start
static_assert_size!(AttrWrapper, 16);
static_assert_size!(LazyAttrTokenStreamImpl, 104);
static_assert_size!(
LazyAttrTokenStreamImpl,
104 + std::mem::size_of::<<Global as Allocator>::CoAllocMeta>()
);
// tidy-alphabetical-end
}
5 changes: 4 additions & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ pub struct Parser<'a> {
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
// it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Parser<'_>, 264);
rustc_data_structures::static_assert_size!(
Parser<'_>,
264 + 4 * mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
);

/// Stores span information about a closure.
#[derive(Clone)]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,7 @@ symbols! {
to_string,
to_string_method,
to_vec,
to_vec_co,
todo_macro,
tool_attributes,
tool_lints,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_trait_selection/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![allow(internal_features)]
#![feature(allocator_api)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extract_if)]
#![feature(global_co_alloc_meta)]
// FIXME CoAlloc #![feature(hash_drain_filter)] ???
#![feature(let_chains)]
#![feature(if_let_guard)]
#![feature(never_type)]
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ pub struct PendingPredicateObligation<'tcx> {

// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PendingPredicateObligation<'_>, 72);
static_assert_size!(
PendingPredicateObligation<'_>,
72 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
);

impl<'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.
Expand Down
72 changes: 58 additions & 14 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@

#![stable(feature = "rust1", since = "1.0.0")]

#[cfg(not(no_global_oom_handling))]
use crate::co_alloc::CoAllocPref;
use core::any::Any;
use core::async_iter::AsyncIterator;
use core::borrow;
Expand Down Expand Up @@ -632,7 +634,10 @@ impl<T> Box<[T]> {
#[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity(len).into_box(len) }
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
unsafe {
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len).into_box(len)
}
}

/// Constructs a new boxed slice with uninitialized contents, with the memory
Expand All @@ -657,7 +662,11 @@ impl<T> Box<[T]> {
#[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
unsafe {
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_zeroed(len)
.into_box(len)
}
}

/// Constructs a new boxed slice with uninitialized contents. Returns an error if
Expand Down Expand Up @@ -692,7 +701,14 @@ impl<T> Box<[T]> {
};
Global.allocate(layout)?.cast()
};
unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
unsafe {
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
ptr.as_ptr(),
len,
Global,
)
.into_box(len))
}
}

/// Constructs a new boxed slice with uninitialized contents, with the memory
Expand Down Expand Up @@ -726,11 +742,22 @@ impl<T> Box<[T]> {
};
Global.allocate_zeroed(layout)?.cast()
};
unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
unsafe {
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
ptr.as_ptr(),
len,
Global,
)
.into_box(len))
}
}
}

impl<T, A: Allocator> Box<[T], A> {
#[allow(unused_braces)]
impl<T, A: Allocator> Box<[T], A>
where
[(); { crate::meta_num_slots!(A, crate::CO_ALLOC_PREF_META_NO!()) }]:,
{
/// Constructs a new boxed slice with uninitialized contents in the provided allocator.
///
/// # Examples
Expand All @@ -757,8 +784,11 @@ impl<T, A: Allocator> Box<[T], A> {
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
#[allow(unused_braces)]
pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) }
unsafe {
RawVec::<T, A, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_in(len, alloc).into_box(len)
}
}

/// Constructs a new boxed slice with uninitialized contents in the provided allocator,
Expand All @@ -785,8 +815,12 @@ impl<T, A: Allocator> Box<[T], A> {
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
#[allow(unused_braces)]
pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) }
unsafe {
RawVec::<T, A, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_zeroed_in(len, alloc)
.into_box(len)
}
}
}

Expand Down Expand Up @@ -1487,7 +1521,7 @@ trait BoxFromSlice<T> {
impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
#[inline]
default fn from_slice(slice: &[T]) -> Self {
slice.to_vec().into_boxed_slice()
slice.to_vec_co::<{ CO_ALLOC_PREF_META_NO!() }>().into_boxed_slice()
}
}

Expand All @@ -1496,7 +1530,7 @@ impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
#[inline]
fn from_slice(slice: &[T]) -> Self {
let len = slice.len();
let buf = RawVec::with_capacity(len);
let buf = RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box(slice.len()).assume_init()
Expand Down Expand Up @@ -1682,8 +1716,13 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
type Error = Vec<T>;
#[allow(unused_braces)]
impl<T, const N: usize, const CO_ALLOC_PREF: CoAllocPref> TryFrom<Vec<T, Global, CO_ALLOC_PREF>>
for Box<[T; N]>
where
[(); { meta_num_slots_global!(CO_ALLOC_PREF) }]:,
{
type Error = Vec<T, Global, CO_ALLOC_PREF>;

/// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
///
Expand All @@ -1703,7 +1742,7 @@ impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
/// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
/// assert_eq!(state.len(), 100);
/// ```
fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
fn try_from(vec: Vec<T, Global, CO_ALLOC_PREF>) -> Result<Self, Self::Error> {
if vec.len() == N {
let boxed_slice = vec.into_boxed_slice();
Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
Expand Down Expand Up @@ -2038,10 +2077,15 @@ impl<I> FromIterator<I> for Box<[I]> {

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
#[allow(unused_braces)]
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A>
where
[(); { crate::meta_num_slots!(A, crate::CO_ALLOC_PREF_META_NO!()) }]:,
{
fn clone(&self) -> Self {
let alloc = Box::allocator(self).clone();
self.to_vec_in(alloc).into_boxed_slice()
// false = no need for co-alloc metadata, since it would get lost once converted to the boxed slice.
self.to_vec_in_co::<A, { CO_ALLOC_PREF_META_NO!() }>(alloc).into_boxed_slice()
}

fn clone_from(&mut self, other: &Self) {
Expand Down
47 changes: 47 additions & 0 deletions library/alloc/src/co_alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! CoAlloction-specific types that only apply in heap-based applications (hence not a part of
//! [::core]).
//!
//! Types here have names with `CoAlloc` prefix. Yes, when using a qualified path (like
//! ::alloc::co_alloc::CoAllocPref), that involves "stuttering", which is not recommended.
//!
//! However, as per Rust Book the common practice is to import type names fully and access them just
//! with their name (except for cases of conflict). And we don't want the type names any shorter
//! (such `Pref`), because thoe would be vague/confusing.

/// `CoAllocPref` values indicate a type's preference for coallocation (in either user space, or
/// `std` space). Used as a `const` generic parameter type (usually called `CO_ALLOC_PREF`).
///
/// The actual value may be overriden by the allocator. See also `CoAllocMetaNumSlotsPref` and
/// `co_alloc_pref` macro .
///
/// This type WILL CHANGE (once ``#![feature(generic_const_exprs)]` and
/// `#![feature(adt_const_params)]` are stable) to a dedicated struct/enum. Hence:
/// - DO NOT construct instances, but use `co_alloc_pref` macro together with constants
/// `CO_ALLOC_PREF_META_YES` and `CO_ALLOC_PREF_META_NO`;
/// - DO NOT hard code any values; and
/// - DO NOT mix this/cast this with/to `u8`, `u16`, `usize` (nor any other integer).
#[unstable(feature = "global_co_alloc_meta", issue = "none")]
pub type CoAllocPref = usize; //u8;

/// `CoAllocMetaNumSlotsPref` values indicate that a type (but not necessarily an allocator) prefers
/// to coallocate by carrying metadata, or not. (In either user space, or `std` or `alloc` space).
/// Used as an argument to macro call of `co_alloc_pref`, which generates a `CoAllocPref` value.
///
/// Currently this indicates only the (preferred) number of `CoAllocMetaBase` slots being used
/// (either 1 = coallocation, or 0 = no coallocation). However, in the future this type may have
/// other properties (serving as extra hints to the allocator).
///
/// The actual value may be overriden by the allocator. For example, if the allocator doesn't
/// support coallocation, then whether this value prefers to coallocate or not makes no difference.
///
/// This type WILL CHANGE (once ``#![feature(generic_const_exprs)]` and
/// `#![feature(adt_const_params)]` are stable) to a dedicated struct/enum. Hence:
/// - DO NOT mix this/cast this with/to `u8`, `u16`, (nor any other integer); and
/// - DO NOT hard code any values, but use `CO_ALLOC_PREF_META_YES` and `CO_ALLOC_PREF_META_NO`.
///
/// This type is intentionally not `u16`, `u32`, nor `usize`. Why? This helps to prevent mistakes
/// when one would use `CO_ALLOC_PREF_META_YES` or `CO_ALLOC_PREF_META_NO` in place of `CoAllocPref`
/// vales, or in place of a result of `meta_num_slots` macro. That also prevents mixing up with
/// [core::alloc::CoAllocatorMetaNumSlots].
#[unstable(feature = "global_co_alloc_meta", issue = "none")]
pub type CoAllocMetaNumSlotsPref = u16;
Loading

0 comments on commit ad541b4

Please sign in to comment.