summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-26 23:15:50 +0100
committerGitHub <noreply@github.com>2024-01-26 23:15:50 +0100
commit975a82b4e2f6faff274b9a4ae4a1f5fa9315d265 (patch)
tree75a2d91a08609c91f1802081897c604d9a5548e5 /library/std/src/sys
parentb31bf24908ef9e4b7e2236eaa133d3d22dbd5912 (diff)
parent27a6e6e67b6585e0f9bebc00617c22709c0d4a7e (diff)
downloadrust-975a82b4e2f6faff274b9a4ae4a1f5fa9315d265.tar.gz
rust-975a82b4e2f6faff274b9a4ae4a1f5fa9315d265.zip
Rollup merge of #120205 - Berrysoft:windows-alloc-init, r=ChrisDenton
std: make `HEAP` initializer never inline

The system allocator for Windows calls `init_or_get_process_heap` every time allocating. It generates very much useless code and makes the binary larger. The `HEAP` only needs to initialize once before the main fn.

Concerns:
* I'm not sure if `init` will be properly called in cdylib.
* Do we need to ensure the allocator works if the user enables `no_main`?
* Should we panic if `GetProcessHeap` returns null?
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/pal/windows/alloc.rs24
1 files changed, 13 insertions, 11 deletions
diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/pal/windows/alloc.rs
index d53ea16005f..270eca37b14 100644
--- a/library/std/src/sys/pal/windows/alloc.rs
+++ b/library/std/src/sys/pal/windows/alloc.rs
@@ -95,7 +95,7 @@ static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
 #[inline]
 fn init_or_get_process_heap() -> c::HANDLE {
     let heap = HEAP.load(Ordering::Relaxed);
-    if heap.is_null() {
+    if core::intrinsics::unlikely(heap.is_null()) {
         // `HEAP` has not yet been successfully initialized
         let heap = unsafe { GetProcessHeap() };
         if !heap.is_null() {
@@ -115,6 +115,16 @@ fn init_or_get_process_heap() -> c::HANDLE {
     }
 }
 
+#[inline(never)]
+fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
+    let heap = init_or_get_process_heap();
+    if core::intrinsics::unlikely(heap.is_null()) {
+        return ptr::null_mut();
+    }
+    // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
+    unsafe { HeapAlloc(heap, flags, dwBytes) }
+}
+
 // Get a non-null handle to the default heap of the current process.
 // SAFETY: `HEAP` must have been successfully initialized.
 #[inline]
@@ -133,25 +143,17 @@ struct Header(*mut u8);
 // initialized.
 #[inline]
 unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
-    let heap = init_or_get_process_heap();
-    if heap.is_null() {
-        // Allocation has failed, could not get the current process heap.
-        return ptr::null_mut();
-    }
-
     // Allocated memory will be either zeroed or uninitialized.
     let flags = if zeroed { HEAP_ZERO_MEMORY } else { 0 };
 
     if layout.align() <= MIN_ALIGN {
-        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
         // The returned pointer points to the start of an allocated block.
-        unsafe { HeapAlloc(heap, flags, layout.size()) as *mut u8 }
+        process_heap_alloc(flags, layout.size()) as *mut u8
     } else {
         // Allocate extra padding in order to be able to satisfy the alignment.
         let total = layout.align() + layout.size();
 
-        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
-        let ptr = unsafe { HeapAlloc(heap, flags, total) as *mut u8 };
+        let ptr = process_heap_alloc(flags, total) as *mut u8;
         if ptr.is_null() {
             // Allocation has failed.
             return ptr::null_mut();