diff --git a/cmake/sources/ZigSources.txt b/cmake/sources/ZigSources.txt index 4544453ac6..4bc15e4ec9 100644 --- a/cmake/sources/ZigSources.txt +++ b/cmake/sources/ZigSources.txt @@ -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 diff --git a/src/allocators.zig b/src/allocators.zig index 6e21740d50..7a11ac9000 100644 --- a/src/allocators.zig +++ b/src/allocators.zig @@ -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"); diff --git a/src/allocators/basic.zig b/src/allocators/basic.zig index f8c3c6b8b5..c8fe13a9e9 100644 --- a/src/allocators/basic.zig +++ b/src/allocators/basic.zig @@ -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"); diff --git a/src/allocators/fallback.zig b/src/allocators/fallback.zig new file mode 100644 index 0000000000..caf389a42f --- /dev/null +++ b/src/allocators/fallback.zig @@ -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"); diff --git a/src/allocators/fallback/z.zig b/src/allocators/fallback/z.zig new file mode 100644 index 0000000000..c44c0debc8 --- /dev/null +++ b/src/allocators/fallback/z.zig @@ -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; diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 8fee145369..f35d56c0c1 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -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 } { diff --git a/src/bun.zig b/src/bun.zig index 7576246022..bcf90190eb 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -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;