Fix z_allocator implementation when use_mimalloc is false; make Bun compile with use_mimalloc false (#21771)

We can't use `std.heap.c_allocator` as `z_allocator`; it doesn't
zero-initialize the memory. This PR adds a fallback implementation.

This PR also makes Bun compile successfully with `use_mimalloc` set to
false. More work is likely necessary to make it function correctly in
this case, but it should at least compile.

(For internal tracking: fixes STAB-978, STAB-979)
This commit is contained in:
taylor.fish
2025-08-11 20:20:58 -07:00
committed by GitHub
parent 41b1efe12c
commit 0c83ff3f7e
7 changed files with 71 additions and 16 deletions

View File

@@ -1,6 +1,8 @@
src/allocators.zig
src/allocators/AllocationScope.zig
src/allocators/basic.zig
src/allocators/fallback.zig
src/allocators/fallback/z.zig
src/allocators/LinuxMemFdAllocator.zig
src/allocators/MaxHeapAllocator.zig
src/allocators/MemoryReportingAllocator.zig

View File

@@ -1,5 +1,6 @@
pub const c_allocator = @import("./allocators/basic.zig").c_allocator;
pub const z_allocator = @import("./allocators/basic.zig").z_allocator;
pub const c_allocator = basic.c_allocator;
pub const z_allocator = basic.z_allocator;
pub const freeWithoutSize = basic.freeWithoutSize;
pub const mimalloc = @import("./allocators/mimalloc.zig");
pub const MimallocArena = @import("./allocators/MimallocArena.zig");
pub const AllocationScope = @import("./allocators/AllocationScope.zig");
@@ -772,6 +773,11 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
};
}
const basic = if (bun.use_mimalloc)
@import("./allocators/basic.zig")
else
@import("./allocators/fallback.zig");
const Environment = @import("./env.zig");
const std = @import("std");

View File

@@ -142,6 +142,11 @@ const z_allocator_vtable = Allocator.VTable{
.free = &ZAllocator.free_with_z_allocator,
};
/// mimalloc can free allocations without being given their size.
pub fn freeWithoutSize(ptr: ?*anyopaque) void {
mimalloc.mi_free(ptr);
}
const Environment = @import("../env.zig");
const std = @import("std");

View File

@@ -0,0 +1,9 @@
pub const c_allocator = std.heap.c_allocator;
pub const z_allocator = @import("./fallback/z.zig").allocator;
/// libc can free allocations without being given their size.
pub fn freeWithoutSize(ptr: ?*anyopaque) void {
std.c.free(ptr);
}
const std = @import("std");

View File

@@ -0,0 +1,43 @@
/// A fallback zero-initializing allocator.
pub const allocator = Allocator{
.ptr = undefined,
.vtable = &vtable,
};
const vtable = Allocator.VTable{
.alloc = alloc,
.resize = resize,
.remap = Allocator.noRemap, // the mimalloc z_allocator doesn't support remap
.free = free,
};
fn alloc(_: *anyopaque, len: usize, alignment: Alignment, return_address: usize) ?[*]u8 {
const result = c_allocator.rawAlloc(len, alignment, return_address) orelse
return null;
@memset(result[0..len], 0);
return result;
}
fn resize(
_: *anyopaque,
buf: []u8,
alignment: Alignment,
new_len: usize,
return_address: usize,
) bool {
if (!c_allocator.rawResize(buf, alignment, new_len, return_address)) {
return false;
}
@memset(buf.ptr[buf.len..new_len], 0);
return true;
}
fn free(_: *anyopaque, buf: []u8, alignment: Alignment, return_address: usize) void {
c_allocator.rawFree(buf, alignment, return_address);
}
const std = @import("std");
const c_allocator = std.heap.c_allocator;
const Alignment = std.mem.Alignment;
const Allocator = std.mem.Allocator;

View File

@@ -1473,8 +1473,7 @@ pub const JSZlib = struct {
reader.deinit();
}
export fn global_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
comptime assert(bun.use_mimalloc);
bun.mimalloc.mi_free(ctx);
bun.allocators.freeWithoutSize(ctx);
}
export fn compressor_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
var compressor: *zlib.ZlibCompressorArrayList = bun.cast(*zlib.ZlibCompressorArrayList, ctx.?);
@@ -1758,8 +1757,7 @@ pub const JSZlib = struct {
pub const JSZstd = struct {
export fn deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
comptime assert(bun.use_mimalloc);
bun.mimalloc.mi_free(ctx);
bun.allocators.freeWithoutSize(ctx);
}
inline fn getOptions(globalThis: *JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!struct { jsc.Node.StringOrBuffer, ?JSValue } {

View File

@@ -9,17 +9,9 @@ const bun = @This();
pub const Environment = @import("./env.zig");
pub const use_mimalloc = true;
pub const default_allocator: std.mem.Allocator = if (use_mimalloc)
allocators.c_allocator
else
std.heap.c_allocator;
pub const default_allocator: std.mem.Allocator = allocators.c_allocator;
/// Zeroing memory allocator
pub const z_allocator: std.mem.Allocator = if (use_mimalloc)
allocators.z_allocator
else
std.heap.c_allocator;
pub const z_allocator: std.mem.Allocator = allocators.z_allocator;
pub const callmod_inline: std.builtin.CallModifier = if (builtin.mode == .Debug) .auto else .always_inline;
pub const callconv_inline: std.builtin.CallingConvention = if (builtin.mode == .Debug) .Unspecified else .Inline;