aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-12 21:55:55 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-12 21:55:55 -0800
commitb1e7d38f72fe464a66475c148e5648a2aabf4476 (patch)
treef7d053f6e0ddf72fca2549b9e1e7e3d5b39b7c61 /src
parentcf566ab785defa1cd5e138cfa53fef8cde3a8665 (diff)
downloadbun-b1e7d38f72fe464a66475c148e5648a2aabf4476.tar.gz
bun-b1e7d38f72fe464a66475c148e5648a2aabf4476.tar.zst
bun-b1e7d38f72fe464a66475c148e5648a2aabf4476.zip
Add a memory allocator that always zeroes
Diffstat (limited to 'src')
-rw-r--r--src/memory_allocator.zig118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/memory_allocator.zig b/src/memory_allocator.zig
index 9b48d6e66..0691b2590 100644
--- a/src/memory_allocator.zig
+++ b/src/memory_allocator.zig
@@ -140,3 +140,121 @@ const c_allocator_vtable = Allocator.VTable{
.resize = CAllocator.resize,
.free = CAllocator.free,
};
+
+// This is a memory allocator which always writes zero instead of undefined
+const ZAllocator = struct {
+ comptime {
+ if (!@import("builtin").link_libc) {
+ @compileError("C allocator is only available when linking against libc");
+ }
+ }
+
+ usingnamespace if (@hasDecl(c, "malloc_size"))
+ struct {
+ pub const supports_malloc_size = true;
+ pub const malloc_size = c.malloc_size;
+ }
+ else if (@hasDecl(c, "malloc_usable_size"))
+ struct {
+ pub const supports_malloc_size = true;
+ pub const malloc_size = c.malloc_usable_size;
+ }
+ else if (@hasDecl(c, "_msize"))
+ struct {
+ pub const supports_malloc_size = true;
+ pub const malloc_size = c._msize;
+ }
+ else
+ struct {
+ pub const supports_malloc_size = false;
+ };
+
+ pub const supports_posix_memalign = true;
+
+ fn getHeader(ptr: [*]u8) *[*]u8 {
+ return @intToPtr(*[*]u8, @ptrToInt(ptr) - @sizeOf(usize));
+ }
+
+ const MI_MAX_ALIGN_SIZE = 16;
+ inline fn mi_malloc_satisfies_alignment(alignment: usize, size: usize) bool {
+ return (alignment == @sizeOf(*anyopaque) or (alignment == MI_MAX_ALIGN_SIZE and size > (MI_MAX_ALIGN_SIZE / 2)));
+ }
+
+ fn alignedAlloc(len: usize, alignment: usize) ?[*]u8 {
+ var ptr = if (mi_malloc_satisfies_alignment(alignment, len))
+ mimalloc.mi_zalloc(len)
+ else
+ mimalloc.mi_zalloc_aligned(len, alignment);
+
+ return @ptrCast([*]u8, ptr orelse null);
+ }
+
+ fn alignedFree(ptr: [*]u8) void {
+ return c.free(ptr);
+ }
+
+ fn alignedAllocSize(ptr: [*]u8) usize {
+ return ZAllocator.malloc_size(ptr);
+ }
+
+ fn alloc(
+ _: *anyopaque,
+ len: usize,
+ alignment: u29,
+ len_align: u29,
+ return_address: usize,
+ ) error{OutOfMemory}![]u8 {
+ _ = return_address;
+ assert(len > 0);
+ assert(std.math.isPowerOfTwo(alignment));
+
+ var ptr = alignedAlloc(len, alignment) orelse return error.OutOfMemory;
+ if (len_align == 0) {
+ return ptr[0..len];
+ }
+ return ptr[0..mem.alignBackwardAnyAlign(mimalloc.mi_usable_size(ptr), len_align)];
+ }
+
+ fn resize(
+ _: *anyopaque,
+ buf: []u8,
+ buf_align: u29,
+ new_len: usize,
+ len_align: u29,
+ return_address: usize,
+ ) ?usize {
+ _ = buf_align;
+ _ = return_address;
+ if (new_len <= buf.len) {
+ return mem.alignAllocLen(buf.len, new_len, len_align);
+ }
+
+ const full_len = alignedAllocSize(buf.ptr);
+ if (new_len <= full_len) {
+ return mem.alignAllocLen(full_len, new_len, len_align);
+ }
+
+ return null;
+ }
+
+ fn free(
+ _: *anyopaque,
+ buf: []u8,
+ buf_align: u29,
+ return_address: usize,
+ ) void {
+ _ = buf_align;
+ _ = return_address;
+ mimalloc.mi_free(buf.ptr);
+ }
+};
+
+pub const z_allocator = Allocator{
+ .ptr = undefined,
+ .vtable = &z_allocator_vtable,
+};
+const z_allocator_vtable = Allocator.VTable{
+ .alloc = ZAllocator.alloc,
+ .resize = ZAllocator.resize,
+ .free = ZAllocator.free,
+};