mirror of
https://github.com/oven-sh/bun
synced 2026-02-11 11:29:02 +00:00
136 lines
4.7 KiB
Zig
136 lines
4.7 KiB
Zig
const bun = @import("bun");
|
|
const std = @import("std");
|
|
const Environment = bun.Environment;
|
|
const Allocator = std.mem.Allocator;
|
|
const vm_size_t = usize;
|
|
|
|
pub const enabled = Environment.allow_assert and Environment.isMac;
|
|
|
|
fn heapLabel(comptime T: type) [:0]const u8 {
|
|
const base_name = if (@hasDecl(T, "heap_label"))
|
|
T.heap_label
|
|
else
|
|
bun.meta.typeBaseName(@typeName(T));
|
|
return base_name;
|
|
}
|
|
|
|
pub fn allocator(comptime T: type) std.mem.Allocator {
|
|
return namedAllocator(comptime heapLabel(T));
|
|
}
|
|
pub fn namedAllocator(comptime name: [:0]const u8) std.mem.Allocator {
|
|
return getZone("Bun__" ++ name).allocator();
|
|
}
|
|
|
|
pub fn getZoneT(comptime T: type) *Zone {
|
|
return getZone(comptime heapLabel(T));
|
|
}
|
|
|
|
pub fn getZone(comptime name: [:0]const u8) *Zone {
|
|
comptime bun.assert(enabled);
|
|
|
|
const static = struct {
|
|
pub var zone: *Zone = undefined;
|
|
pub fn initOnce() void {
|
|
zone = Zone.init(name);
|
|
}
|
|
|
|
pub var once = std.once(initOnce);
|
|
};
|
|
|
|
static.once.call();
|
|
return static.zone;
|
|
}
|
|
|
|
pub const Zone = opaque {
|
|
pub fn init(comptime name: [:0]const u8) *Zone {
|
|
const zone = malloc_create_zone(0, 0);
|
|
|
|
malloc_set_zone_name(zone, name.ptr);
|
|
|
|
return zone;
|
|
}
|
|
|
|
fn alignedAlloc(zone: *Zone, len: usize, alignment: std.mem.Alignment) ?[*]u8 {
|
|
// The posix_memalign only accepts alignment values that are a
|
|
// multiple of the pointer size
|
|
const eff_alignment = @max(alignment.toByteUnits(), @sizeOf(usize));
|
|
const ptr = malloc_zone_memalign(zone, eff_alignment, len);
|
|
return @as(?[*]u8, @ptrCast(ptr));
|
|
}
|
|
|
|
fn alignedAllocSize(ptr: [*]u8) usize {
|
|
return std.c.malloc_size(ptr);
|
|
}
|
|
|
|
fn rawAlloc(zone: *anyopaque, len: usize, alignment: std.mem.Alignment, _: usize) ?[*]u8 {
|
|
return alignedAlloc(@ptrCast(zone), len, alignment);
|
|
}
|
|
|
|
fn resize(_: *anyopaque, buf: []u8, _: std.mem.Alignment, new_len: usize, _: usize) bool {
|
|
if (new_len <= buf.len) {
|
|
return true;
|
|
}
|
|
|
|
const full_len = alignedAllocSize(buf.ptr);
|
|
if (new_len <= full_len) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
fn rawFree(zone: *anyopaque, buf: []u8, _: std.mem.Alignment, _: usize) void {
|
|
malloc_zone_free(@ptrCast(zone), @ptrCast(buf.ptr));
|
|
}
|
|
|
|
pub const vtable = std.mem.Allocator.VTable{
|
|
.alloc = &rawAlloc,
|
|
.resize = &resize,
|
|
.remap = &std.mem.Allocator.noRemap,
|
|
.free = &rawFree,
|
|
};
|
|
|
|
pub fn allocator(zone: *Zone) std.mem.Allocator {
|
|
return .{
|
|
.vtable = &vtable,
|
|
.ptr = zone,
|
|
};
|
|
}
|
|
|
|
/// Create a single-item pointer with initialized data.
|
|
pub inline fn create(zone: *Zone, comptime T: type, data: T) *T {
|
|
const alignment: std.mem.Alignment = .fromByteUnits(@alignOf(T));
|
|
const ptr: *T = @alignCast(@ptrCast(
|
|
rawAlloc(zone, @sizeOf(T), alignment, @returnAddress()) orelse bun.outOfMemory(),
|
|
));
|
|
ptr.* = data;
|
|
return ptr;
|
|
}
|
|
|
|
/// Free a single-item pointer
|
|
pub inline fn destroy(zone: *Zone, comptime T: type, ptr: *T) void {
|
|
malloc_zone_free(zone, @ptrCast(ptr));
|
|
}
|
|
|
|
pub extern fn malloc_default_zone() *Zone;
|
|
pub extern fn malloc_create_zone(start_size: vm_size_t, flags: c_uint) *Zone;
|
|
pub extern fn malloc_destroy_zone(zone: *Zone) void;
|
|
pub extern fn malloc_zone_malloc(zone: *Zone, size: usize) ?*anyopaque;
|
|
pub extern fn malloc_zone_calloc(zone: *Zone, num_items: usize, size: usize) ?*anyopaque;
|
|
pub extern fn malloc_zone_valloc(zone: *Zone, size: usize) ?*anyopaque;
|
|
pub extern fn malloc_zone_free(zone: *Zone, ptr: ?*anyopaque) void;
|
|
pub extern fn malloc_zone_realloc(zone: *Zone, ptr: ?*anyopaque, size: usize) ?*anyopaque;
|
|
pub extern fn malloc_zone_from_ptr(ptr: ?*const anyopaque) *Zone;
|
|
pub extern fn malloc_zone_memalign(zone: *Zone, alignment: usize, size: usize) ?*anyopaque;
|
|
pub extern fn malloc_zone_batch_malloc(zone: *Zone, size: usize, results: [*]?*anyopaque, num_requested: c_uint) c_uint;
|
|
pub extern fn malloc_zone_batch_free(zone: *Zone, to_be_freed: [*]?*anyopaque, num: c_uint) void;
|
|
pub extern fn malloc_default_purgeable_zone() *Zone;
|
|
pub extern fn malloc_make_purgeable(ptr: ?*anyopaque) void;
|
|
pub extern fn malloc_make_nonpurgeable(ptr: ?*anyopaque) c_int;
|
|
pub extern fn malloc_zone_register(zone: *Zone) void;
|
|
pub extern fn malloc_zone_unregister(zone: *Zone) void;
|
|
pub extern fn malloc_set_zone_name(zone: *Zone, name: ?[*:0]const u8) void;
|
|
pub extern fn malloc_get_zone_name(zone: *Zone) ?[*:0]const u8;
|
|
pub extern fn malloc_zone_pressure_relief(zone: *Zone, goal: usize) usize;
|
|
};
|