forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
38: Update libgc to use single allocator r=ltratt a=jacob-hughes `libgc_internal` now uses a single allocator for both the `Allocator` and `GlobalAlloc` trait. This PR updates `libgc` to use that. Co-authored-by: Jake Hughes <jh@jakehughes.uk>
- Loading branch information
Showing
8 changed files
with
473 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
//! This library acts as a shim to prevent static linking the Boehm GC directly | ||
//! inside library/alloc which causes surprising and hard to debug errors. | ||
|
||
#![allow(dead_code)] | ||
|
||
use core::{ | ||
alloc::{AllocError, Allocator, GlobalAlloc, Layout}, | ||
ptr::NonNull, | ||
}; | ||
|
||
pub struct GcAllocator; | ||
|
||
use crate::boehm; | ||
#[cfg(feature = "rustgc")] | ||
use crate::specializer; | ||
|
||
#[cfg(feature = "rustgc")] | ||
pub(crate) static ALLOCATOR: GcAllocator = GcAllocator; | ||
|
||
unsafe impl GlobalAlloc for GcAllocator { | ||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | ||
#[cfg(feature = "rustgc")] | ||
return boehm::GC_malloc(layout.size()) as *mut u8; | ||
#[cfg(not(feature = "rustgc"))] | ||
return boehm::GC_malloc_uncollectable(layout.size()) as *mut u8; | ||
} | ||
|
||
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { | ||
boehm::GC_free(ptr); | ||
} | ||
|
||
unsafe fn realloc(&self, ptr: *mut u8, _: Layout, new_size: usize) -> *mut u8 { | ||
boehm::GC_realloc(ptr, new_size) as *mut u8 | ||
} | ||
|
||
#[cfg(feature = "rustgc_internal")] | ||
unsafe fn alloc_precise(&self, layout: Layout, bitmap: usize, bitmap_size: usize) -> *mut u8 { | ||
let gc_descr = boehm::GC_make_descriptor(&bitmap, bitmap_size); | ||
boehm::GC_malloc_explicitly_typed(layout.size(), gc_descr) as *mut u8 | ||
} | ||
|
||
#[cfg(feature = "rustgc_internal")] | ||
fn alloc_conservative(&self, layout: Layout) -> *mut u8 { | ||
unsafe { boehm::GC_malloc(layout.size()) as *mut u8 } | ||
} | ||
|
||
#[cfg(feature = "rustgc_internal")] | ||
unsafe fn alloc_atomic(&self, layout: Layout) -> *mut u8 { | ||
boehm::GC_malloc_atomic(layout.size()) as *mut u8 | ||
} | ||
} | ||
|
||
unsafe impl Allocator for GcAllocator { | ||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { | ||
let ptr = unsafe { boehm::GC_malloc(layout.size()) } as *mut u8; | ||
assert!(!ptr.is_null()); | ||
let ptr = unsafe { NonNull::new_unchecked(ptr) }; | ||
Ok(NonNull::slice_from_raw_parts(ptr, layout.size())) | ||
} | ||
|
||
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {} | ||
} | ||
|
||
impl GcAllocator { | ||
#[cfg(feature = "rustgc_internal")] | ||
pub fn maybe_optimised_alloc<T>(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { | ||
let sp = specializer::AllocationSpecializer::new(); | ||
sp.maybe_optimised_alloc::<T>(layout) | ||
} | ||
|
||
pub fn force_gc() { | ||
unsafe { boehm::GC_gcollect() } | ||
} | ||
|
||
pub unsafe fn register_finalizer( | ||
&self, | ||
obj: *mut u8, | ||
finalizer: Option<unsafe extern "C" fn(*mut u8, *mut u8)>, | ||
client_data: *mut u8, | ||
old_finalizer: *mut extern "C" fn(*mut u8, *mut u8), | ||
old_client_data: *mut *mut u8, | ||
) { | ||
boehm::GC_register_finalizer_no_order( | ||
obj, | ||
finalizer, | ||
client_data, | ||
old_finalizer, | ||
old_client_data, | ||
) | ||
} | ||
|
||
pub fn unregister_finalizer(&self, gcbox: *mut u8) { | ||
unsafe { | ||
boehm::GC_register_finalizer( | ||
gcbox, | ||
None, | ||
::core::ptr::null_mut(), | ||
::core::ptr::null_mut(), | ||
::core::ptr::null_mut(), | ||
); | ||
} | ||
} | ||
|
||
pub fn get_stats() -> GcStats { | ||
let mut ps = boehm::ProfileStats::default(); | ||
unsafe { | ||
boehm::GC_get_prof_stats( | ||
&mut ps as *mut boehm::ProfileStats, | ||
core::mem::size_of::<boehm::ProfileStats>(), | ||
); | ||
} | ||
let total_gc_time = unsafe { boehm::GC_get_full_gc_total_time() }; | ||
|
||
GcStats { | ||
total_gc_time, | ||
num_collections: ps.gc_no, | ||
total_freed: ps.bytes_reclaimed_since_gc, | ||
total_alloced: ps.bytes_allocd_since_gc, | ||
} | ||
} | ||
|
||
pub fn init() { | ||
unsafe { boehm::GC_start_performance_measurement() }; | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct GcStats { | ||
total_gc_time: usize, // In milliseconds. | ||
num_collections: usize, | ||
total_freed: usize, // In bytes | ||
total_alloced: usize, // In bytes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#[repr(C)] | ||
#[derive(Default)] | ||
pub struct ProfileStats { | ||
/// Heap size in bytes (including area unmapped to OS). | ||
pub(crate) heapsize_full: usize, | ||
/// Total bytes contained in free and unmapped blocks. | ||
pub(crate) free_bytes_full: usize, | ||
/// Amount of memory unmapped to OS. | ||
pub(crate) unmapped_bytes: usize, | ||
/// Number of bytes allocated since the recent collection. | ||
pub(crate) bytes_allocd_since_gc: usize, | ||
/// Number of bytes allocated before the recent collection. | ||
/// The value may wrap. | ||
pub(crate) allocd_bytes_before_gc: usize, | ||
/// Number of bytes not considered candidates for garbage collection. | ||
pub(crate) non_gc_bytes: usize, | ||
/// Garbage collection cycle number. | ||
/// The value may wrap. | ||
pub(crate) gc_no: usize, | ||
/// Number of marker threads (excluding the initiating one). | ||
pub(crate) markers_m1: usize, | ||
/// Approximate number of reclaimed bytes after recent collection. | ||
pub(crate) bytes_reclaimed_since_gc: usize, | ||
/// Approximate number of bytes reclaimed before the recent collection. | ||
/// The value may wrap. | ||
pub(crate) reclaimed_bytes_before_gc: usize, | ||
/// Number of bytes freed explicitly since the recent GC. | ||
pub(crate) expl_freed_bytes_since_gc: usize, | ||
} | ||
|
||
#[link(name = "gc")] | ||
extern "C" { | ||
pub(crate) fn GC_malloc(nbytes: usize) -> *mut u8; | ||
|
||
#[cfg(not(feature = "rustgc"))] | ||
pub(crate) fn GC_malloc_uncollectable(nbytes: usize) -> *mut u8; | ||
|
||
pub(crate) fn GC_realloc(old: *mut u8, new_size: usize) -> *mut u8; | ||
|
||
pub(crate) fn GC_free(dead: *mut u8); | ||
|
||
pub(crate) fn GC_register_finalizer( | ||
ptr: *mut u8, | ||
finalizer: Option<unsafe extern "C" fn(*mut u8, *mut u8)>, | ||
client_data: *mut u8, | ||
old_finalizer: *mut extern "C" fn(*mut u8, *mut u8), | ||
old_client_data: *mut *mut u8, | ||
); | ||
|
||
pub(crate) fn GC_register_finalizer_no_order( | ||
ptr: *mut u8, | ||
finalizer: Option<unsafe extern "C" fn(*mut u8, *mut u8)>, | ||
client_data: *mut u8, | ||
old_finalizer: *mut extern "C" fn(*mut u8, *mut u8), | ||
old_client_data: *mut *mut u8, | ||
); | ||
|
||
pub(crate) fn GC_gcollect(); | ||
|
||
pub(crate) fn GC_start_performance_measurement(); | ||
|
||
pub(crate) fn GC_get_full_gc_total_time() -> usize; | ||
|
||
pub(crate) fn GC_get_prof_stats(prof_stats: *mut ProfileStats, stats_size: usize) -> usize; | ||
|
||
#[cfg(feature = "rustgc")] | ||
pub(crate) fn GC_malloc_explicitly_typed(size: usize, descriptor: usize) -> *mut u8; | ||
|
||
#[cfg(feature = "rustgc")] | ||
pub(crate) fn GC_make_descriptor(bitmap: *const usize, len: usize) -> usize; | ||
|
||
#[cfg(feature = "rustgc")] | ||
pub(crate) fn GC_malloc_atomic(nbytes: usize) -> *mut u8; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.