| ... | @@ -12,7 +12,7 @@ pub const ArenaAllocator = struct { | ... | @@ -12,7 +12,7 @@ pub const ArenaAllocator = struct { |
| 12 | /// Inner state of ArenaAllocator. Can be stored rather than the entire ArenaAllocator | 12 | /// Inner state of ArenaAllocator. Can be stored rather than the entire ArenaAllocator |
| 13 | /// as a memory-saving optimization. | 13 | /// as a memory-saving optimization. |
| 14 | pub const State = struct { | 14 | pub const State = struct { |
| 15 | buffer_list: std.SinglyLinkedList([]u8) = @as(std.SinglyLinkedList([]u8), .{}), | 15 | buffer_list: std.SinglyLinkedList(usize) = .{}, |
| 16 | end_index: usize = 0, | 16 | end_index: usize = 0, |
| 17 | | 17 | |
| 18 | pub fn promote(self: State, child_allocator: Allocator) ArenaAllocator { | 18 | pub fn promote(self: State, child_allocator: Allocator) ArenaAllocator { |
| ... | @@ -34,7 +34,7 @@ pub const ArenaAllocator = struct { | ... | @@ -34,7 +34,7 @@ pub const ArenaAllocator = struct { |
| 34 | }; | 34 | }; |
| 35 | } | 35 | } |
| 36 | | 36 | |
| 37 | const BufNode = std.SinglyLinkedList([]u8).Node; | 37 | const BufNode = std.SinglyLinkedList(usize).Node; |
| 38 | | 38 | |
| 39 | pub fn init(child_allocator: Allocator) ArenaAllocator { | 39 | pub fn init(child_allocator: Allocator) ArenaAllocator { |
| 40 | return (State{}).promote(child_allocator); | 40 | return (State{}).promote(child_allocator); |
| ... | @@ -47,7 +47,9 @@ pub const ArenaAllocator = struct { | ... | @@ -47,7 +47,9 @@ pub const ArenaAllocator = struct { |
| 47 | while (it) |node| { | 47 | while (it) |node| { |
| 48 | // this has to occur before the free because the free frees node | 48 | // this has to occur before the free because the free frees node |
| 49 | const next_it = node.next; | 49 | const next_it = node.next; |
| 50 | self.child_allocator.free(node.data); | 50 | const align_bits = std.math.log2_int(usize, @alignOf(BufNode)); |
| | 51 | const alloc_buf = @ptrCast([*]u8, node)[0..node.data]; |
| | 52 | self.child_allocator.rawFree(alloc_buf, align_bits, @returnAddress()); |
| 51 | it = next_it; | 53 | it = next_it; |
| 52 | } | 54 | } |
| 53 | } | 55 | } |
| ... | @@ -73,7 +75,7 @@ pub const ArenaAllocator = struct { | ... | @@ -73,7 +75,7 @@ pub const ArenaAllocator = struct { |
| 73 | while (it) |node| : (it = node.next) { | 75 | while (it) |node| : (it = node.next) { |
| 74 | // Compute the actually allocated size excluding the | 76 | // Compute the actually allocated size excluding the |
| 75 | // linked list node. | 77 | // linked list node. |
| 76 | size += node.data.len - @sizeOf(BufNode); | 78 | size += node.data - @sizeOf(BufNode); |
| 77 | } | 79 | } |
| 78 | return size; | 80 | return size; |
| 79 | } | 81 | } |
| ... | @@ -121,6 +123,7 @@ pub const ArenaAllocator = struct { | ... | @@ -121,6 +123,7 @@ pub const ArenaAllocator = struct { |
| 121 | .retain_with_limit => |limit| std.math.min(limit, current_capacity), | 123 | .retain_with_limit => |limit| std.math.min(limit, current_capacity), |
| 122 | .free_all => unreachable, | 124 | .free_all => unreachable, |
| 123 | }; | 125 | }; |
| | 126 | const align_bits = std.math.log2_int(usize, @alignOf(BufNode)); |
| 124 | // Free all nodes except for the last one | 127 | // Free all nodes except for the last one |
| 125 | var it = self.state.buffer_list.first; | 128 | var it = self.state.buffer_list.first; |
| 126 | const maybe_first_node = while (it) |node| { | 129 | const maybe_first_node = while (it) |node| { |
| ... | @@ -128,7 +131,8 @@ pub const ArenaAllocator = struct { | ... | @@ -128,7 +131,8 @@ pub const ArenaAllocator = struct { |
| 128 | const next_it = node.next; | 131 | const next_it = node.next; |
| 129 | if (next_it == null) | 132 | if (next_it == null) |
| 130 | break node; | 133 | break node; |
| 131 | self.child_allocator.free(node.data); | 134 | const alloc_buf = @ptrCast([*]u8, node)[0..node.data]; |
| | 135 | self.child_allocator.rawFree(alloc_buf, align_bits, @returnAddress()); |
| 132 | it = next_it; | 136 | it = next_it; |
| 133 | } else null; | 137 | } else null; |
| 134 | std.debug.assert(maybe_first_node == null or maybe_first_node.?.next == null); | 138 | std.debug.assert(maybe_first_node == null or maybe_first_node.?.next == null); |
| ... | @@ -136,23 +140,21 @@ pub const ArenaAllocator = struct { | ... | @@ -136,23 +140,21 @@ pub const ArenaAllocator = struct { |
| 136 | self.state.end_index = 0; | 140 | self.state.end_index = 0; |
| 137 | if (maybe_first_node) |first_node| { | 141 | if (maybe_first_node) |first_node| { |
| 138 | // perfect, no need to invoke the child_allocator | 142 | // perfect, no need to invoke the child_allocator |
| 139 | if (first_node.data.len == total_size) | 143 | if (first_node.data == total_size) |
| 140 | return true; | 144 | return true; |
| 141 | const align_bits = std.math.log2_int(usize, @alignOf(BufNode)); | 145 | const first_alloc_buf = @ptrCast([*]u8, first_node)[0..first_node.data]; |
| 142 | if (self.child_allocator.rawResize(first_node.data, align_bits, total_size, @returnAddress())) { | 146 | if (self.child_allocator.rawResize(first_alloc_buf, align_bits, total_size, @returnAddress())) { |
| 143 | // successful resize | 147 | // successful resize |
| 144 | first_node.data.len = total_size; | 148 | first_node.data = total_size; |
| 145 | } else { | 149 | } else { |
| 146 | // manual realloc | 150 | // manual realloc |
| 147 | const new_ptr = self.child_allocator.rawAlloc(total_size, align_bits, @returnAddress()) orelse { | 151 | const new_ptr = self.child_allocator.rawAlloc(total_size, align_bits, @returnAddress()) orelse { |
| 148 | // we failed to preheat the arena properly, signal this to the user. | 152 | // we failed to preheat the arena properly, signal this to the user. |
| 149 | return false; | 153 | return false; |
| 150 | }; | 154 | }; |
| 151 | self.child_allocator.rawFree(first_node.data, align_bits, @returnAddress()); | 155 | self.child_allocator.rawFree(first_alloc_buf, align_bits, @returnAddress()); |
| 152 | const node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), new_ptr)); | 156 | const node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), new_ptr)); |
| 153 | node.* = BufNode{ | 157 | node.* = .{ .data = total_size }; |
| 154 | .data = new_ptr[0..total_size], | | |
| 155 | }; | | |
| 156 | self.state.buffer_list.first = node; | 158 | self.state.buffer_list.first = node; |
| 157 | } | 159 | } |
| 158 | } | 160 | } |
| ... | @@ -167,10 +169,7 @@ pub const ArenaAllocator = struct { | ... | @@ -167,10 +169,7 @@ pub const ArenaAllocator = struct { |
| 167 | const ptr = self.child_allocator.rawAlloc(len, log2_align, @returnAddress()) orelse | 169 | const ptr = self.child_allocator.rawAlloc(len, log2_align, @returnAddress()) orelse |
| 168 | return null; | 170 | return null; |
| 169 | const buf_node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), ptr)); | 171 | const buf_node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), ptr)); |
| 170 | buf_node.* = BufNode{ | 172 | buf_node.* = .{ .data = len }; |
| 171 | .data = ptr[0..len], | | |
| 172 | .next = null, | | |
| 173 | }; | | |
| 174 | self.state.buffer_list.prepend(buf_node); | 173 | self.state.buffer_list.prepend(buf_node); |
| 175 | self.state.end_index = 0; | 174 | self.state.end_index = 0; |
| 176 | return buf_node; | 175 | return buf_node; |
| ... | @@ -186,7 +185,8 @@ pub const ArenaAllocator = struct { | ... | @@ -186,7 +185,8 @@ pub const ArenaAllocator = struct { |
| 186 | else | 185 | else |
| 187 | (self.createNode(0, n + ptr_align) orelse return null); | 186 | (self.createNode(0, n + ptr_align) orelse return null); |
| 188 | while (true) { | 187 | while (true) { |
| 189 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; | 188 | const cur_alloc_buf = @ptrCast([*]u8, cur_node)[0..cur_node.data]; |
| | 189 | const cur_buf = cur_alloc_buf[@sizeOf(BufNode)..]; |
| 190 | const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index; | 190 | const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index; |
| 191 | const adjusted_addr = mem.alignForward(addr, ptr_align); | 191 | const adjusted_addr = mem.alignForward(addr, ptr_align); |
| 192 | const adjusted_index = self.state.end_index + (adjusted_addr - addr); | 192 | const adjusted_index = self.state.end_index + (adjusted_addr - addr); |
| ... | @@ -199,8 +199,9 @@ pub const ArenaAllocator = struct { | ... | @@ -199,8 +199,9 @@ pub const ArenaAllocator = struct { |
| 199 | } | 199 | } |
| 200 | | 200 | |
| 201 | const bigger_buf_size = @sizeOf(BufNode) + new_end_index; | 201 | const bigger_buf_size = @sizeOf(BufNode) + new_end_index; |
| 202 | if (self.child_allocator.resize(cur_node.data, bigger_buf_size)) { | 202 | const log2_align = comptime std.math.log2_int(usize, @alignOf(BufNode)); |
| 203 | cur_node.data.len = bigger_buf_size; | 203 | if (self.child_allocator.rawResize(cur_alloc_buf, log2_align, bigger_buf_size, @returnAddress())) { |
| | 204 | cur_node.data = bigger_buf_size; |
| 204 | } else { | 205 | } else { |
| 205 | // Allocate a new node if that's not possible | 206 | // Allocate a new node if that's not possible |
| 206 | cur_node = self.createNode(cur_buf.len, n + ptr_align) orelse return null; | 207 | cur_node = self.createNode(cur_buf.len, n + ptr_align) orelse return null; |
| ... | @@ -214,7 +215,7 @@ pub const ArenaAllocator = struct { | ... | @@ -214,7 +215,7 @@ pub const ArenaAllocator = struct { |
| 214 | _ = ret_addr; | 215 | _ = ret_addr; |
| 215 | | 216 | |
| 216 | const cur_node = self.state.buffer_list.first orelse return false; | 217 | const cur_node = self.state.buffer_list.first orelse return false; |
| 217 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; | 218 | const cur_buf = @ptrCast([*]u8, cur_node)[@sizeOf(BufNode)..cur_node.data]; |
| 218 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index != @ptrToInt(buf.ptr) + buf.len) { | 219 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index != @ptrToInt(buf.ptr) + buf.len) { |
| 219 | // It's not the most recent allocation, so it cannot be expanded, | 220 | // It's not the most recent allocation, so it cannot be expanded, |
| 220 | // but it's fine if they want to make it smaller. | 221 | // but it's fine if they want to make it smaller. |
| ... | @@ -239,7 +240,7 @@ pub const ArenaAllocator = struct { | ... | @@ -239,7 +240,7 @@ pub const ArenaAllocator = struct { |
| 239 | const self = @ptrCast(*ArenaAllocator, @alignCast(@alignOf(ArenaAllocator), ctx)); | 240 | const self = @ptrCast(*ArenaAllocator, @alignCast(@alignOf(ArenaAllocator), ctx)); |
| 240 | | 241 | |
| 241 | const cur_node = self.state.buffer_list.first orelse return; | 242 | const cur_node = self.state.buffer_list.first orelse return; |
| 242 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; | 243 | const cur_buf = @ptrCast([*]u8, cur_node)[@sizeOf(BufNode)..cur_node.data]; |
| 243 | | 244 | |
| 244 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index == @ptrToInt(buf.ptr) + buf.len) { | 245 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index == @ptrToInt(buf.ptr) + buf.len) { |
| 245 | self.state.end_index -= buf.len; | 246 | self.state.end_index -= buf.len; |