Skip to content

Commit d8853f8

Browse files
committed
Use shared statics for the ArcInner for Arc<str, CStr>::default, and for Arc<[T]>::default where alignof(T) <= 16.
1 parent a5d0757 commit d8853f8

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

Diff for: alloc/src/ffi/c_str.rs

-13
Original file line numberDiff line numberDiff line change
@@ -910,19 +910,6 @@ impl From<&CStr> for Rc<CStr> {
910910
}
911911
}
912912

913-
#[cfg(not(no_global_oom_handling))]
914-
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
915-
impl Default for Arc<CStr> {
916-
/// Creates an empty CStr inside an Arc
917-
///
918-
/// This may or may not share an allocation with other Arcs.
919-
#[inline]
920-
fn default() -> Self {
921-
let c_str: &CStr = Default::default();
922-
Arc::from(c_str)
923-
}
924-
}
925-
926913
#[cfg(not(no_global_oom_handling))]
927914
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
928915
impl Default for Rc<CStr> {

Diff for: alloc/src/sync.rs

+51-1
Original file line numberDiff line numberDiff line change
@@ -3308,7 +3308,32 @@ impl Default for Arc<str> {
33083308
/// This may or may not share an allocation with other Arcs.
33093309
#[inline]
33103310
fn default() -> Self {
3311-
Arc::from("")
3311+
let arc: Arc<[u8]> = Default::default();
3312+
debug_assert!(core::str::from_utf8(&*arc).is_ok());
3313+
let (ptr, alloc) = Arc::into_inner_with_allocator(arc);
3314+
unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner<str>, alloc) }
3315+
}
3316+
}
3317+
3318+
#[cfg(not(no_global_oom_handling))]
3319+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
3320+
impl Default for Arc<core::ffi::CStr> {
3321+
/// Creates an empty CStr inside an Arc
3322+
///
3323+
/// This may or may not share an allocation with other Arcs.
3324+
#[inline]
3325+
fn default() -> Self {
3326+
use core::ffi::CStr;
3327+
static STATIC_INNER_CSTR: ArcInner<[u8; 1]> = ArcInner {
3328+
strong: atomic::AtomicUsize::new(1),
3329+
weak: atomic::AtomicUsize::new(1),
3330+
data: [0],
3331+
};
3332+
let inner: NonNull<ArcInner<[u8]>> = NonNull::from(&STATIC_INNER_CSTR);
3333+
let inner: NonNull<ArcInner<CStr>> = NonNull::new(inner.as_ptr() as *mut ArcInner<CStr>).unwrap();
3334+
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3335+
let this: mem::ManuallyDrop<Arc<CStr>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
3336+
(*this).clone()
33123337
}
33133338
}
33143339

@@ -3320,6 +3345,31 @@ impl<T> Default for Arc<[T]> {
33203345
/// This may or may not share an allocation with other Arcs.
33213346
#[inline]
33223347
fn default() -> Self {
3348+
let alignment_of_t: usize = mem::align_of::<T>();
3349+
// We only make statics for the lowest five alignments.
3350+
// Alignments greater than that will use dynamic allocation.
3351+
macro_rules! use_static_inner_for_alignments {
3352+
($($alignment:literal),*) => {
3353+
$(if alignment_of_t == $alignment {
3354+
// Note: this must be in a new scope because static and type names are unhygenic.
3355+
#[repr(align($alignment))]
3356+
struct Aligned;
3357+
static ALIGNED_STATIC_INNER: ArcInner<Aligned> = ArcInner {
3358+
strong: atomic::AtomicUsize::new(1),
3359+
weak: atomic::AtomicUsize::new(1),
3360+
data: Aligned,
3361+
};
3362+
let inner: NonNull<ArcInner<Aligned>> = NonNull::from(&ALIGNED_STATIC_INNER);
3363+
let inner: NonNull<ArcInner<[T; 0]>> = inner.cast();
3364+
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3365+
let this: mem::ManuallyDrop<Arc<[T; 0]>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
3366+
return (*this).clone();
3367+
})*
3368+
};
3369+
}
3370+
use_static_inner_for_alignments!(1, 2, 4, 8, 16);
3371+
3372+
// If T's alignment is not one of the ones we have a static for, make a new unique allocation.
33233373
let arr: [T; 0] = [];
33243374
Arc::from(arr)
33253375
}

0 commit comments

Comments
 (0)