Skip to content

Commit

Permalink
Auto merge of rust-lang#131888 - ChrisDenton:deopt, r=ibraheemdev
Browse files Browse the repository at this point in the history
Revert using `HEAP` static in Windows alloc

Fixes rust-lang#131468

This does the minimum to remove the `HEAP` static that was causing chromium issues. It would be worth having a more substantial look at this module but for now I think this addresses the immediate issue.

cc `@danakj`
  • Loading branch information
bors committed Nov 7, 2024
2 parents 52c2a45 + 7f6af4d commit 7a82eb5
Showing 1 changed file with 12 additions and 57 deletions.
69 changes: 12 additions & 57 deletions std/src/sys/alloc/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ffi::c_void;
use crate::mem::MaybeUninit;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::c;

#[cfg(test)]
Expand Down Expand Up @@ -81,69 +80,25 @@ windows_targets::link!("kernel32.dll" "system" fn HeapReAlloc(
// See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree
windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap: c::HANDLE, dwflags: u32, lpmem: *const c_void) -> c::BOOL);

// Cached handle to the default heap of the current process.
// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed.
static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());

// Get a handle to the default heap of the current process, or null if the operation fails.
// If this operation is successful, `HEAP` will be successfully initialized and contain
// a non-null handle returned by `GetProcessHeap`.
#[inline]
fn init_or_get_process_heap() -> c::HANDLE {
// `HEAP` has not yet been successfully initialized
let heap = unsafe { GetProcessHeap() };
if !heap.is_null() {
// SAFETY: No locking is needed because within the same process,
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
HEAP.store(heap, Ordering::Release);

// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
heap
} else {
// Could not get the current process heap.
ptr::null_mut()
}
fn get_process_heap() -> *mut c_void {
// SAFETY: GetProcessHeap simply returns a valid handle or NULL so is always safe to call.
unsafe { GetProcessHeap() }
}

/// This is outlined from `process_heap_alloc` so that `process_heap_alloc`
/// does not need any stack allocations.
#[inline(never)]
#[cold]
extern "C" fn process_heap_init_and_alloc(
_heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`
fn process_heap_alloc(
_heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
flags: u32,
bytes: usize,
) -> *mut c_void {
let heap = init_or_get_process_heap();
let heap = 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, bytes) }
}

#[inline(never)]
fn process_heap_alloc(
_heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
flags: u32,
bytes: usize,
) -> *mut c_void {
let heap = HEAP.load(Ordering::Relaxed);
if core::intrinsics::likely(!heap.is_null()) {
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
unsafe { HeapAlloc(heap, flags, bytes) }
} else {
process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes)
}
}

// Get a non-null handle to the default heap of the current process.
// SAFETY: `HEAP` must have been successfully initialized.
#[inline]
unsafe fn get_process_heap() -> c::HANDLE {
HEAP.load(Ordering::Acquire)
}

// Header containing a pointer to the start of an allocated block.
// SAFETY: Size and alignment must be <= `MIN_ALIGN`.
#[repr(C)]
Expand Down Expand Up @@ -232,9 +187,9 @@ unsafe impl GlobalAlloc for System {
}
};

// SAFETY: because `ptr` has been successfully allocated with this allocator,
// `HEAP` must have been successfully initialized.
let heap = unsafe { get_process_heap() };
// because `ptr` has been successfully allocated with this allocator,
// there must be a valid process heap.
let heap = get_process_heap();

// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
// `block` is a pointer to the start of an allocated block.
Expand All @@ -244,9 +199,9 @@ unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= MIN_ALIGN {
// SAFETY: because `ptr` has been successfully allocated with this allocator,
// `HEAP` must have been successfully initialized.
let heap = unsafe { get_process_heap() };
// because `ptr` has been successfully allocated with this allocator,
// there must be a valid process heap.
let heap = get_process_heap();

// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
// `ptr` is a pointer to the start of an allocated block.
Expand Down

0 comments on commit 7a82eb5

Please sign in to comment.