forked from oven-sh/bun
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathc_thunks.rs
More file actions
113 lines (102 loc) · 5.41 KB
/
Copy pathc_thunks.rs
File metadata and controls
113 lines (102 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! C-ABI allocator thunks routing C library allocator hooks to the default allocator.
//!
//! | ABI | alloc signature | free signature |
//! |----------------------------------|------------------------------------------|----------------------------|
//! | zlib `alloc_func`/`free_func` | `(opaque, items: c_uint, size: c_uint)` | `(opaque, ptr)` |
//! | brotli `brotli_alloc/free_func` | `(opaque, size: usize)` | `(opaque, ptr)` |
//! | JSC `JSTypedArrayBytesDeallocator` | — | `(bytes, ctx)` |
//!
//! The plain (non-zone-tagged) variants are free functions below; the
//! zone-tagged variants are minted per-label by [`c_thunks_for_zone!`].
use core::ffi::{c_uint, c_void};
use crate::default_alloc as raw;
// ──────────────────────────────────────────────────────────────────────────
// Plain default-allocator thunks (no heap-breakdown tagging)
// ──────────────────────────────────────────────────────────────────────────
/// zlib `alloc_func` → default allocator `malloc(items * size)` (non-zeroing).
pub extern "C" fn mi_malloc_items(_: *mut c_void, items: c_uint, size: c_uint) -> *mut c_void {
let p = raw::malloc((items * size) as usize);
if p.is_null() {
unreachable!();
}
p
}
/// `(opaque, ptr)` → default allocator `free(ptr)`; opaque cookie ignored.
pub unsafe extern "C" fn mi_free_opaque(_: *mut c_void, ptr: *mut c_void) {
// SAFETY: ptr was allocated by the default allocator (or is null).
unsafe { raw::free(ptr) };
}
/// JSC `JSTypedArrayBytesDeallocator` → default allocator `free(ctx)`; `bytes` ignored.
pub use mi_free_opaque as mi_free_ctx;
/// JSC `JSTypedArrayBytesDeallocator` → default allocator `free(bytes)`; `ctx` ignored.
pub unsafe extern "C" fn mi_free_bytes(bytes: *mut c_void, _ctx: *mut c_void) {
// SAFETY: bytes was allocated by the default allocator (or is null).
unsafe { raw::free(bytes) };
}
// ──────────────────────────────────────────────────────────────────────────
// Zone-tagged thunks
// ──────────────────────────────────────────────────────────────────────────
/// Expands a set of `extern "C"` allocator thunks bound to a named
/// heap-breakdown zone. When `heap_breakdown::ENABLED` is false (release /
/// non-macOS) the thunks fall straight through to the default allocator.
///
/// Generated items:
/// - `malloc_size(_, len: usize) -> *mut c_void` — brotli-shape, non-zeroing.
/// Safe `extern "C" fn` (opaque cookie ignored; body is all-safe).
/// - `calloc_items(_, items: c_uint, len: c_uint) -> *mut c_void` — zlib-shape,
/// zeroing. Safe `extern "C" fn` (same rationale).
/// - `free(_, ptr: *mut c_void)` — paired with either alloc. `unsafe`
/// (precondition: `ptr` was allocated by this zone / the default allocator).
///
/// Intended to be invoked inside a `mod XxxAllocator { … }` so call sites can
/// keep referring to `XxxAllocator::alloc` / `::free` via a local `pub use`.
#[macro_export]
macro_rules! c_thunks_for_zone {
($name:literal) => {
pub extern "C" fn malloc_size(
_: *mut ::core::ffi::c_void,
len: usize,
) -> *mut ::core::ffi::c_void {
if $crate::heap_breakdown::ENABLED {
return match $crate::get_zone!($name).malloc_zone_malloc(len) {
Some(p) => p,
None => $crate::out_of_memory(),
};
}
let p = $crate::default_alloc::malloc(len);
if p.is_null() {
$crate::out_of_memory();
}
p
}
pub extern "C" fn calloc_items(
_: *mut ::core::ffi::c_void,
items: ::core::ffi::c_uint,
len: ::core::ffi::c_uint,
) -> *mut ::core::ffi::c_void {
if $crate::heap_breakdown::ENABLED {
return match $crate::get_zone!($name)
.malloc_zone_calloc(items as usize, len as usize)
{
Some(p) => p,
None => $crate::out_of_memory(),
};
}
let p = $crate::default_alloc::calloc(items as usize, len as usize);
if p.is_null() {
$crate::out_of_memory();
}
p
}
pub unsafe extern "C" fn free(_: *mut ::core::ffi::c_void, data: *mut ::core::ffi::c_void) {
if $crate::heap_breakdown::ENABLED {
// SAFETY: `data` was allocated by this zone in one of the
// alloc thunks above.
unsafe { $crate::get_zone!($name).malloc_zone_free(data) };
return;
}
// SAFETY: data was allocated by the default allocator (or is null).
unsafe { $crate::default_alloc::free(data) };
}
};
}