Skip to content

Commit 9933e87

Browse files
committed
perf experiment: try to replace box_new with write_via_move
1 parent 7487954 commit 9933e87

File tree

7 files changed

+43
-20
lines changed

7 files changed

+43
-20
lines changed

library/alloc/src/alloc.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,15 @@ unsafe impl Allocator for Global {
343343
}
344344

345345
/// The allocator for `Box`.
346+
///
347+
/// # Safety
348+
///
349+
/// `size` and `align` must satisfy the conditions in [`Layout::from_size_align`].
346350
#[cfg(not(no_global_oom_handling))]
347351
#[lang = "exchange_malloc"]
348352
#[inline]
349353
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
350-
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
354+
pub(crate) unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
351355
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
352356
match Global.allocate(layout) {
353357
Ok(ptr) => ptr.as_mut_ptr(),

library/alloc/src/boxed.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ use core::task::{Context, Poll};
203203

204204
#[cfg(not(no_global_oom_handling))]
205205
use crate::alloc::handle_alloc_error;
206-
use crate::alloc::{AllocError, Allocator, Global, Layout};
206+
use crate::alloc::{AllocError, Allocator, Global, Layout, exchange_malloc};
207207
use crate::raw_vec::RawVec;
208208
#[cfg(not(no_global_oom_handling))]
209209
use crate::str::from_boxed_utf8_unchecked;
@@ -259,7 +259,15 @@ impl<T> Box<T> {
259259
#[rustc_diagnostic_item = "box_new"]
260260
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
261261
pub fn new(x: T) -> Self {
262-
return box_new(x);
262+
// SAFETY: the size and align of a valid type `T` are always valid for `Layout`.
263+
let ptr = unsafe {
264+
exchange_malloc(<T as SizedTypeProperties>::SIZE, <T as SizedTypeProperties>::ALIGN)
265+
} as *mut T;
266+
// Nothing below can panic so we do not have to worry about deallocating `ptr`.
267+
// SAFETY: we just allocated the box to store `x`.
268+
unsafe { core::intrinsics::write_via_move(ptr, x) };
269+
// SAFETY: we just initialized `b`.
270+
unsafe { mem::transmute(ptr) }
263271
}
264272

265273
/// Constructs a new box with uninitialized contents.

tests/mir-opt/building/write_via_move.box_new.built.after.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// MIR for `box_new` after built
22

33
| User Type Annotations
4-
| 0: user_ty: Canonical { value: TypeOf(DefId(3:681 ~ alloc[0ef6]::boxed::{impl#0}::new_uninit), UserArgs { args: [^c_0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(3:678 ~ alloc[0ef6]::boxed::{impl#0}), self_ty: std::boxed::Box<^c_1, ^c_2> }) }), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }, Ty { ui: U0, sub_root: 2 }] }, span: $DIR/write_via_move.rs:11:17: 11:32, inferred_ty: fn() -> std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>> {std::boxed::Box::<[T; 1024]>::new_uninit}
5-
| 1: user_ty: Canonical { value: TypeOf(DefId(2:2175 ~ core[d5fa]::mem::maybe_uninit::{impl#2}::as_mut_ptr), UserArgs { args: [^c_0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(2:2168 ~ core[d5fa]::mem::maybe_uninit::{impl#2}), self_ty: std::mem::MaybeUninit<^c_1> }) }), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }] }, span: $DIR/write_via_move.rs:12:15: 12:43, inferred_ty: for<'a> fn(&'a mut std::mem::MaybeUninit<[T; 1024]>) -> *mut [T; 1024] {std::mem::MaybeUninit::<[T; 1024]>::as_mut_ptr}
4+
| 0: user_ty: Canonical { value: TypeOf(DefId(3:682 ~ alloc[78d6]::boxed::{impl#0}::new_uninit), UserArgs { args: [^c_0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(3:679 ~ alloc[78d6]::boxed::{impl#0}), self_ty: std::boxed::Box<^c_1, ^c_2> }) }), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }, Ty { ui: U0, sub_root: 2 }] }, span: $DIR/write_via_move.rs:11:17: 11:32, inferred_ty: fn() -> std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>> {std::boxed::Box::<[T; 1024]>::new_uninit}
5+
| 1: user_ty: Canonical { value: TypeOf(DefId(2:2175 ~ core[cfc2]::mem::maybe_uninit::{impl#2}::as_mut_ptr), UserArgs { args: [^c_0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(2:2168 ~ core[cfc2]::mem::maybe_uninit::{impl#2}), self_ty: std::mem::MaybeUninit<^c_1> }) }), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }] }, span: $DIR/write_via_move.rs:12:15: 12:43, inferred_ty: for<'a> fn(&'a mut std::mem::MaybeUninit<[T; 1024]>) -> *mut [T; 1024] {std::mem::MaybeUninit::<[T; 1024]>::as_mut_ptr}
66
|
77
fn box_new(_1: T) -> Box<[T; 1024]> {
88
debug x => _1;

tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@
213213
+ StorageLive(_42);
214214
+ _42 = Option::<()>::None;
215215
+ _35 = copy ((*_37).0: std::option::Option<()>);
216-
+ ((*_37).0: std::option::Option<()>) = copy _42;
216+
+ ((*_37).0: std::option::Option<()>) = move _42;
217217
+ StorageDead(_42);
218218
+ StorageLive(_43);
219219
+ _43 = discriminant(_35);
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
22
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
33
|
4-
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
4+
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::SIZE` failed here
55

66
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
77
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
88
|
9-
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::ALIGN` failed here
9+
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::ALIGN` failed here
10+
11+
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new_uninit_in`
12+
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
1013

11-
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new`
12-
--> $DIR/issue-17913.rs:16:21
14+
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
15+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
1316
|
14-
LL | let a: Box<_> = Box::new([&n; SIZE]);
15-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
18+
19+
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::try_new_uninit_in`
20+
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
1621

17-
error: aborting due to 2 previous errors
22+
error: aborting due to 3 previous errors
1823

1924
For more information about this error, try `rustc --explain E0080`.
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
22
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
33
|
4-
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
4+
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::SIZE` failed here
55

66
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
77
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
88
|
9-
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::ALIGN` failed here
9+
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::ALIGN` failed here
10+
11+
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new_uninit_in`
12+
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
1013

11-
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new`
12-
--> $DIR/issue-17913.rs:9:21
14+
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
15+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
1316
|
14-
LL | let a: Box<_> = Box::new([&n; SIZE]);
15-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
18+
19+
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::try_new_uninit_in`
20+
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
1621

17-
error: aborting due to 2 previous errors
22+
error: aborting due to 3 previous errors
1823

1924
For more information about this error, try `rustc --explain E0080`.

tests/ui/limits/issue-17913.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ fn main() {
1919

2020
//~? ERROR are too big for the target architecture
2121
//~? ERROR are too big for the target architecture
22+
//~? ERROR are too big for the target architecture

0 commit comments

Comments
 (0)