diff options
Diffstat (limited to 'src/memory.zig')
| -rw-r--r-- | src/memory.zig | 84 |
1 files changed, 43 insertions, 41 deletions
diff --git a/src/memory.zig b/src/memory.zig index a2c5547c..b8a64a1a 100644 --- a/src/memory.zig +++ b/src/memory.zig @@ -48,48 +48,54 @@ pub const Allocators = struct { /// lock-free interface. The core's allocator is used from two threads: a 9P /// connection task answers a request while the editor's own thread is out /// in a syscall that allocates (`readFileLimit`, `grep`; see `pardes.turn`). -fn SharedStackFallback(comptime size: usize) type { - return struct { - buffer: [size]u8 = undefined, - fallback_allocator: Allocator = undefined, - fixed: std.heap.FixedBufferAllocator = undefined, +/// The buffer is a separate zeroed global, not a field: an `undefined` one is +/// written into a Debug binary as 0xAA filler, 160 MB of file for the five +/// arenas, where a zeroed one is .bss and costs nothing. +const SharedStackFallback = struct { + buffer: []u8, + fallback_allocator: Allocator = undefined, + fixed: std.heap.FixedBufferAllocator = undefined, - fn get(self: *@This()) Allocator { - self.fixed = .init(self.buffer[0..]); - return .{ .ptr = self, .vtable = &.{ .alloc = alloc, .resize = resize, .remap = remap, .free = free } }; - } + fn get(self: *@This()) Allocator { + self.fixed = .init(self.buffer); + return .{ .ptr = self, .vtable = &.{ .alloc = alloc, .resize = resize, .remap = remap, .free = free } }; + } - fn alloc(ctx: *anyopaque, len: usize, alignment: std.mem.Alignment, ra: usize) ?[*]u8 { - const self: *@This() = @ptrCast(@alignCast(ctx)); - return self.fixed.threadSafeAllocator().rawAlloc(len, alignment, ra) orelse - self.fallback_allocator.rawAlloc(len, alignment, ra); - } + fn alloc(ctx: *anyopaque, len: usize, alignment: std.mem.Alignment, ra: usize) ?[*]u8 { + const self: *@This() = @ptrCast(@alignCast(ctx)); + return self.fixed.threadSafeAllocator().rawAlloc(len, alignment, ra) orelse + self.fallback_allocator.rawAlloc(len, alignment, ra); + } - fn resize(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) bool { - const self: *@This() = @ptrCast(@alignCast(ctx)); - if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawResize(buf, alignment, new_len, ra); - return self.fallback_allocator.rawResize(buf, alignment, new_len, ra); - } + fn resize(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) bool { + const self: *@This() = @ptrCast(@alignCast(ctx)); + if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawResize(buf, alignment, new_len, ra); + return self.fallback_allocator.rawResize(buf, alignment, new_len, ra); + } - fn remap(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) ?[*]u8 { - const self: *@This() = @ptrCast(@alignCast(ctx)); - if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawRemap(buf, alignment, new_len, ra); - return self.fallback_allocator.rawRemap(buf, alignment, new_len, ra); - } + fn remap(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) ?[*]u8 { + const self: *@This() = @ptrCast(@alignCast(ctx)); + if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawRemap(buf, alignment, new_len, ra); + return self.fallback_allocator.rawRemap(buf, alignment, new_len, ra); + } - fn free(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, ra: usize) void { - const self: *@This() = @ptrCast(@alignCast(ctx)); - if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawFree(buf, alignment, ra); - return self.fallback_allocator.rawFree(buf, alignment, ra); - } - }; -} + fn free(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, ra: usize) void { + const self: *@This() = @ptrCast(@alignCast(ctx)); + if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawFree(buf, alignment, ra); + return self.fallback_allocator.rawFree(buf, alignment, ra); + } +}; -var pardes_fallback: SharedStackFallback(limits.arena.pardes) = .{}; -var frame_fallback: std.heap.StackFallbackAllocator(limits.arena.frame) = undefined; -var tree_sitter_fallback: std.heap.StackFallbackAllocator(limits.arena.tree_sitter) = undefined; -var image_fallback: std.heap.StackFallbackAllocator(limits.arena.image) = undefined; -var pdf_fallback: std.heap.StackFallbackAllocator(limits.arena.pdf) = undefined; +var pardes_buffer: [limits.arena.pardes]u8 = @splat(0); +var frame_buffer: [limits.arena.frame]u8 = @splat(0); +var tree_sitter_buffer: [limits.arena.tree_sitter]u8 = @splat(0); +var image_buffer: [limits.arena.image]u8 = @splat(0); +var pdf_buffer: [limits.arena.pdf]u8 = @splat(0); +var pardes_fallback: SharedStackFallback = .{ .buffer = &pardes_buffer }; +var frame_fallback: SharedStackFallback = .{ .buffer = &frame_buffer }; +var tree_sitter_fallback: SharedStackFallback = .{ .buffer = &tree_sitter_buffer }; +var image_fallback: SharedStackFallback = .{ .buffer = &image_buffer }; +var pdf_fallback: SharedStackFallback = .{ .buffer = &pdf_buffer }; const Debug = std.heap.DebugAllocator(.{}); var pardes_debug: Debug = .init; @@ -109,13 +115,9 @@ pub fn init(fallback: Allocator) Allocators { const backing = if (debug_enabled) std.heap.page_allocator else fallback; pardes_fallback.fallback_allocator = backing; frame_fallback.fallback_allocator = backing; - frame_fallback.get_called = if (std.debug.runtime_safety) false else {}; tree_sitter_fallback.fallback_allocator = backing; - tree_sitter_fallback.get_called = if (std.debug.runtime_safety) false else {}; image_fallback.fallback_allocator = backing; - image_fallback.get_called = if (std.debug.runtime_safety) false else {}; pdf_fallback.fallback_allocator = backing; - pdf_fallback.get_called = if (std.debug.runtime_safety) false else {}; const raw: Allocators = .{ .pardes = pardes_fallback.get(), @@ -159,7 +161,7 @@ test "fixed allocators are separate, spill, and restart" { const core = try allocs.pardes.alloc(u8, 32); const frame = try allocs.frame.alloc(u8, 32); try std.testing.expect(pardes_fallback.fixed.ownsPtr(core.ptr)); - try std.testing.expect(frame_fallback.fixed_buffer_allocator.ownsPtr(frame.ptr)); + try std.testing.expect(frame_fallback.fixed.ownsPtr(frame.ptr)); try std.testing.expect(core.ptr != frame.ptr); const spill = try allocs.pardes.alloc(u8, limits.arena.pardes + 1); |
