diff options
| author | 2022-11-19 21:37:31 -0800 | |
|---|---|---|
| committer | 2022-11-19 21:37:31 -0800 | |
| commit | 9c601542d0faf7d94c6828f3b7890e3eae9b957e (patch) | |
| tree | 9a2541f9838c74c8cb9d603c43160d7d28c340d7 /src/mimalloc_arena.zig | |
| parent | 7c7769a7c7db3b7932a2726adb9d64e011c1bed6 (diff) | |
| download | bun-9c601542d0faf7d94c6828f3b7890e3eae9b957e.tar.gz bun-9c601542d0faf7d94c6828f3b7890e3eae9b957e.tar.zst bun-9c601542d0faf7d94c6828f3b7890e3eae9b957e.zip | |
Update to Mimalloc v2.0.7
Diffstat (limited to '')
| -rw-r--r-- | src/mimalloc_arena.zig | 124 |
1 files changed, 111 insertions, 13 deletions
diff --git a/src/mimalloc_arena.zig b/src/mimalloc_arena.zig index a313c7dfe..5b2fa14e8 100644 --- a/src/mimalloc_arena.zig +++ b/src/mimalloc_arena.zig @@ -7,9 +7,88 @@ const Environment = @import("./env.zig"); const FeatureFlags = @import("./feature_flags.zig"); const Allocator = mem.Allocator; const assert = std.debug.assert; +const bun = @import("./global.zig"); + +pub const GlobalArena = struct { + arena: Arena, + fallback_allocator: std.mem.Allocator, + + pub fn initWithCapacity(capacity: usize, fallback: std.mem.Allocator) error{OutOfMemory}!GlobalArena { + const arena = try Arena.initWithCapacity(capacity); + + return GlobalArena{ + .arena = arena, + .fallback_allocator = fallback, + }; + } + + pub fn allocator(this: *GlobalArena) Allocator { + return std.mem.Allocator.init(this, alloc, resize, free); + } + + fn alloc( + self: *GlobalArena, + len: usize, + ptr_align: u29, + len_align: u29, + return_address: usize, + ) error{OutOfMemory}![]u8 { + return self.arena.alloc(len, ptr_align, len_align, return_address) catch + return self.fallback_allocator.rawAlloc(len, ptr_align, len_align, return_address); + } + + fn resize( + self: *GlobalArena, + buf: []u8, + buf_align: u29, + new_len: usize, + len_align: u29, + return_address: usize, + ) ?usize { + if (self.arena.ownsPtr(buf.ptr)) { + return self.arena.resize(buf, buf_align, new_len, len_align, return_address); + } else { + return self.fallback_allocator.rawResize(buf, buf_align, new_len, len_align, return_address); + } + } + + fn free( + self: *GlobalArena, + buf: []u8, + buf_align: u29, + return_address: usize, + ) void { + if (self.arena.ownsPtr(buf.ptr)) { + return self.arena.free(buf, buf_align, return_address); + } else { + return self.fallback_allocator.rawFree(buf, buf_align, return_address); + } + } +}; pub const Arena = struct { - heap: ?*mimalloc.mi_heap_t = null, + heap: ?*mimalloc.Heap = null, + arena_id: mimalloc.ArenaID = -1, + + pub fn initWithCapacity(capacity: usize) error{OutOfMemory}!Arena { + var arena_id: mimalloc.ArenaID = -1; + + std.debug.assert(capacity >= 8 * 1024 * 1024); // mimalloc requires a minimum of 8MB + // which makes this not very useful for us! + + if (!mimalloc.mi_manage_os_memory_ex(null, capacity, true, true, false, -1, true, &arena_id)) { + if (!mimalloc.mi_manage_os_memory_ex(null, capacity, false, false, false, -1, true, &arena_id)) { + return error.OutOfMemory; + } + } + std.debug.assert(arena_id != -1); + + var heap = mimalloc.mi_heap_new_in_arena(arena_id) orelse return error.OutOfMemory; + return Arena{ + .heap = heap, + .arena_id = arena_id, + }; + } /// Internally, mimalloc calls mi_heap_get_default() /// to get the default heap. @@ -30,13 +109,31 @@ pub const Arena = struct { } pub fn deinit(this: *Arena) void { - mimalloc.mi_heap_destroy(this.heap); + mimalloc.mi_heap_destroy(this.heap.?); this.heap = null; } pub fn dumpThreadStats(_: *Arena) void { - mimalloc.mi_thread_stats_print_out(null, null); + const dump_fn = struct { + pub fn dump(textZ: [*:0]const u8, _: ?*anyopaque) callconv(.C) void { + const text = bun.span(textZ); + bun.Output.errorWriter().writeAll(text) catch {}; + } + }.dump; + mimalloc.mi_thread_stats_print_out(dump_fn, null); + bun.Output.flush(); + } + + pub fn dumpStats(_: *Arena) void { + const dump_fn = struct { + pub fn dump(textZ: [*:0]const u8, _: ?*anyopaque) callconv(.C) void { + const text = bun.span(textZ); + bun.Output.errorWriter().writeAll(text) catch {}; + } + }.dump; + mimalloc.mi_stats_print_out(dump_fn, null); + bun.Output.flush(); } pub fn reset(this: *Arena) void { @@ -49,7 +146,11 @@ pub const Arena = struct { } pub fn gc(this: Arena, force: bool) void { - mimalloc.mi_heap_collect(this.heap, force); + mimalloc.mi_heap_collect(this.heap orelse return, force); + } + + pub fn ownsPtr(this: Arena, ptr: *const anyopaque) bool { + return mimalloc.mi_heap_check_owned(this.heap.?, ptr); } // Copied from rust @@ -59,19 +160,16 @@ pub const Arena = struct { (alignment == MI_MAX_ALIGN_SIZE and size > (MI_MAX_ALIGN_SIZE / 2))); } - fn alignedAlloc(heap: *mimalloc.mi_heap_t, len: usize, alignment: usize) ?[*]u8 { + fn alignedAlloc(heap: *mimalloc.Heap, len: usize, alignment: usize) ?[*]u8 { if (comptime FeatureFlags.log_allocations) std.debug.print("Malloc: {d}\n", .{len}); // this is the logic that posix_memalign does - var ptr = if (mi_malloc_satisfies_alignment(alignment, len)) - mimalloc.mi_heap_malloc(heap, len) - else - mimalloc.mi_heap_malloc_aligned(heap, len, alignment); + var ptr = mimalloc.mi_heap_malloc_aligned(heap, len, alignment); return @ptrCast([*]u8, ptr orelse null); } - fn alloc( + pub fn alloc( arena: *anyopaque, len: usize, alignment: u29, @@ -82,7 +180,7 @@ pub const Arena = struct { assert(len > 0); assert(std.math.isPowerOfTwo(alignment)); - var ptr = alignedAlloc(@ptrCast(*mimalloc.mi_heap_t, arena), len, alignment) orelse return error.OutOfMemory; + var ptr = alignedAlloc(@ptrCast(*mimalloc.Heap, arena), len, alignment) orelse return error.OutOfMemory; if (len_align == 0) { return ptr[0..len]; } @@ -98,7 +196,7 @@ pub const Arena = struct { } } - fn resize( + pub fn resize( _: *anyopaque, buf: []u8, buf_align: u29, @@ -121,7 +219,7 @@ pub const Arena = struct { return null; } - fn free( + pub fn free( _: *anyopaque, buf: []u8, buf_align: u29, |
