summaryrefslogtreecommitdiff
path: root/src/memory.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory.zig')
-rw-r--r--src/memory.zig84
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);