| ... | @@ -15,7 +15,6 @@ pub const ArenaAllocator = struct { | ... | @@ -15,7 +15,6 @@ pub const ArenaAllocator = struct { |
| 15 | /// as a memory-saving optimization. | 15 | /// as a memory-saving optimization. |
| 16 | pub const State = struct { | 16 | pub const State = struct { |
| 17 | buffer_list: std.SinglyLinkedList([]u8) = @as(std.SinglyLinkedList([]u8), .{}), | 17 | buffer_list: std.SinglyLinkedList([]u8) = @as(std.SinglyLinkedList([]u8), .{}), |
| 18 | /// The first available index in the front buffer of `buffer_list` | | |
| 19 | end_index: usize = 0, | 18 | end_index: usize = 0, |
| 20 | | 19 | |
| 21 | pub fn promote(self: State, child_allocator: *Allocator) ArenaAllocator { | 20 | pub fn promote(self: State, child_allocator: *Allocator) ArenaAllocator { |
| ... | @@ -46,36 +45,39 @@ pub const ArenaAllocator = struct { | ... | @@ -46,36 +45,39 @@ pub const ArenaAllocator = struct { |
| 46 | } | 45 | } |
| 47 | } | 46 | } |
| 48 | | 47 | |
| 49 | fn getBufNodeAddr(buf: []u8) usize { | 48 | fn createNode(self: *ArenaAllocator, prev_len: usize, minimum_size: usize) !*BufNode { |
| 50 | return mem.alignBackward(@ptrToInt(buf.ptr) + buf.len - @sizeOf(BufNode), @alignOf(BufNode)); | 49 | const actual_min_size = minimum_size + (@sizeOf(BufNode) + 16); |
| 51 | } | 50 | const big_enough_len = prev_len + actual_min_size; |
| 52 | | 51 | const len = big_enough_len + big_enough_len / 2; |
| 53 | fn allocBuf(self: *ArenaAllocator, len: usize, ptr_align: u29) ![]u8 { | 52 | const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len); |
| 54 | const alloc_len = len + @sizeOf(BufNode) + @alignOf(BufNode) - 1; | 53 | const buf_node_slice = mem.bytesAsSlice(BufNode, buf[0..@sizeOf(BufNode)]); |
| 55 | const buf = try self.child_allocator.callAllocFn(alloc_len, ptr_align, 1); | 54 | const buf_node = &buf_node_slice[0]; |
| 56 | const buf_node = @intToPtr(*BufNode, getBufNodeAddr(buf)); | 55 | buf_node.* = BufNode{ |
| 57 | buf_node.* = .{ .data = buf, .next = null }; | 56 | .data = buf, |
| 58 | assert(@ptrToInt(buf_node) - @ptrToInt(buf.ptr) >= len); | 57 | .next = null, |
| | 58 | }; |
| 59 | self.state.buffer_list.prepend(buf_node); | 59 | self.state.buffer_list.prepend(buf_node); |
| 60 | self.state.end_index = len; | 60 | self.state.end_index = 0; |
| 61 | return buf[0..len]; | 61 | return buf_node; |
| 62 | } | 62 | } |
| 63 | | 63 | |
| 64 | fn alloc(allocator: *Allocator, n: usize, ptr_align: u29, len_align: u29) ![]u8 { | 64 | fn alloc(allocator: *Allocator, n: usize, ptr_align: u29, len_align: u29) ![]u8 { |
| 65 | const self = @fieldParentPtr(ArenaAllocator, "allocator", allocator); | 65 | const self = @fieldParentPtr(ArenaAllocator, "allocator", allocator); |
| 66 | | 66 | |
| 67 | if (self.state.buffer_list.first) |node_full_buf| { | 67 | var cur_node = if (self.state.buffer_list.first) |first_node| first_node else try self.createNode(0, n + ptr_align); |
| 68 | assert(self.state.end_index > 0); | 68 | while (true) { |
| 69 | const cur_buf = node_full_buf.data[0.. | 69 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; |
| 70 | getBufNodeAddr(node_full_buf.data) - @ptrToInt(node_full_buf.data.ptr)]; | | |
| 71 | const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index; | 70 | const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index; |
| 72 | const aligned_index = self.state.end_index + (mem.alignForward(addr, ptr_align) - addr); | 71 | const adjusted_addr = mem.alignForward(addr, ptr_align); |
| 73 | const aligned_end_index = aligned_index + n; | 72 | const adjusted_index = self.state.end_index + (adjusted_addr - addr); |
| 74 | if (aligned_end_index <= cur_buf.len) { | 73 | const new_end_index = adjusted_index + n; |
| 75 | self.state.end_index = aligned_end_index; | 74 | if (new_end_index > cur_buf.len) { |
| 76 | return cur_buf[aligned_index..aligned_end_index]; | 75 | cur_node = try self.createNode(cur_buf.len, n + ptr_align); |
| | 76 | continue; |
| 77 | } | 77 | } |
| | 78 | const result = cur_buf[adjusted_index..new_end_index]; |
| | 79 | self.state.end_index = new_end_index; |
| | 80 | return result; |
| 78 | } | 81 | } |
| 79 | return try self.allocBuf(n, ptr_align); | | |
| 80 | } | 82 | } |
| 81 | }; | 83 | }; |