| ... | @@ -539,91 +539,79 @@ fn alloc(ctx: *anyopaque, n: usize, alignment: Alignment, ret_addr: usize) ?[*]u | ... | @@ -539,91 +539,79 @@ fn alloc(ctx: *anyopaque, n: usize, alignment: Alignment, ret_addr: usize) ?[*]u |
| 539 | } | 539 | } |
| 540 | } | 540 | } |
| 541 | | 541 | |
| 542 | fn resize(ctx: *anyopaque, buf: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool { | 542 | fn resize(ctx: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool { |
| 543 | const arena: *ArenaAllocator = @ptrCast(@alignCast(ctx)); | 543 | const arena: *ArenaAllocator = @ptrCast(@alignCast(ctx)); |
| 544 | _ = alignment; | 544 | _ = alignment; |
| 545 | _ = ret_addr; | 545 | _ = ret_addr; |
| 546 | | 546 | |
| 547 | assert(buf.len > 0); | 547 | assert(memory.len > 0); |
| 548 | assert(new_len > 0); | 548 | assert(new_len > 0); |
| 549 | if (buf.len == new_len) return true; | | |
| 550 | | 549 | |
| 551 | const node = arena.loadFirstNode().?; | 550 | const node = arena.loadFirstNode().?; |
| 552 | const cur_buf_ptr = @as([*]u8, @ptrCast(node)) + @sizeOf(Node); | 551 | const buf_ptr = @as([*]u8, @ptrCast(node)) + @sizeOf(Node); |
| 553 | | | |
| 554 | var cur_end_index = @atomicLoad(usize, &node.end_index, .monotonic); | | |
| 555 | while (true) { | | |
| 556 | if (cur_buf_ptr + cur_end_index != buf.ptr + buf.len) { | | |
| 557 | // It's not the most recent allocation, so it cannot be expanded, | | |
| 558 | // but it's fine if they want to make it smaller. | | |
| 559 | return new_len <= buf.len; | | |
| 560 | } | | |
| 561 | | 552 | |
| 562 | const new_end_index: usize = new_end_index: { | 553 | const cur_end_index = @atomicLoad(usize, &node.end_index, .monotonic); |
| 563 | if (buf.len >= new_len) { | 554 | if (buf_ptr + cur_end_index != memory.ptr + memory.len) { |
| 564 | break :new_end_index cur_end_index - (buf.len - new_len); | 555 | // It's not the most recent allocation, so it cannot be expanded, |
| 565 | } | 556 | // but it's fine if they want to make it smaller. |
| 566 | const cur_buf_len: usize = node.loadBuf().len; | 557 | return new_len <= memory.len; |
| 567 | // Saturating arithmetic because `end_index` and `size` are not | | |
| 568 | // guaranteed to be in sync. | | |
| 569 | if (cur_buf_len -| cur_end_index >= new_len - buf.len) { | | |
| 570 | break :new_end_index cur_end_index + (new_len - buf.len); | | |
| 571 | } | | |
| 572 | return false; | | |
| 573 | }; | | |
| 574 | | | |
| 575 | cur_end_index = @cmpxchgWeak( | | |
| 576 | usize, | | |
| 577 | &node.end_index, | | |
| 578 | cur_end_index, | | |
| 579 | new_end_index, | | |
| 580 | .monotonic, | | |
| 581 | .monotonic, | | |
| 582 | ) orelse { | | |
| 583 | return true; | | |
| 584 | }; | | |
| 585 | } | 558 | } |
| | 559 | |
| | 560 | const new_end_index: usize = new_end_index: { |
| | 561 | if (memory.len >= new_len) { |
| | 562 | break :new_end_index cur_end_index - (memory.len - new_len); |
| | 563 | } |
| | 564 | const cur_buf_len: usize = node.loadBuf().len; |
| | 565 | // Saturating arithmetic because `end_index` and `size` are not |
| | 566 | // guaranteed to be in sync. |
| | 567 | if (cur_buf_len -| cur_end_index >= new_len - memory.len) { |
| | 568 | break :new_end_index cur_end_index + (new_len - memory.len); |
| | 569 | } |
| | 570 | return false; |
| | 571 | }; |
| | 572 | assert(buf_ptr + new_end_index == memory.ptr + new_len); |
| | 573 | |
| | 574 | return null == @cmpxchgStrong( |
| | 575 | usize, |
| | 576 | &node.end_index, |
| | 577 | cur_end_index, |
| | 578 | new_end_index, |
| | 579 | .monotonic, |
| | 580 | .monotonic, |
| | 581 | ); |
| 586 | } | 582 | } |
| 587 | | 583 | |
| 588 | fn remap( | 584 | fn remap(ctx: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { |
| 589 | context: *anyopaque, | 585 | return if (resize(ctx, memory, alignment, new_len, ret_addr)) memory.ptr else null; |
| 590 | memory: []u8, | | |
| 591 | alignment: Alignment, | | |
| 592 | new_len: usize, | | |
| 593 | return_address: usize, | | |
| 594 | ) ?[*]u8 { | | |
| 595 | return if (resize(context, memory, alignment, new_len, return_address)) memory.ptr else null; | | |
| 596 | } | 586 | } |
| 597 | | 587 | |
| 598 | fn free(ctx: *anyopaque, buf: []u8, alignment: Alignment, ret_addr: usize) void { | 588 | fn free(ctx: *anyopaque, memory: []u8, alignment: Alignment, ret_addr: usize) void { |
| 599 | const arena: *ArenaAllocator = @ptrCast(@alignCast(ctx)); | 589 | const arena: *ArenaAllocator = @ptrCast(@alignCast(ctx)); |
| 600 | _ = alignment; | 590 | _ = alignment; |
| 601 | _ = ret_addr; | 591 | _ = ret_addr; |
| 602 | | 592 | |
| 603 | assert(buf.len > 0); | 593 | assert(memory.len > 0); |
| 604 | | 594 | |
| 605 | const node = arena.loadFirstNode().?; | 595 | const node = arena.loadFirstNode().?; |
| 606 | const cur_buf_ptr: [*]u8 = @as([*]u8, @ptrCast(node)) + @sizeOf(Node); | 596 | const buf_ptr = @as([*]u8, @ptrCast(node)) + @sizeOf(Node); |
| 607 | | 597 | |
| 608 | var cur_end_index = @atomicLoad(usize, &node.end_index, .monotonic); | 598 | const cur_end_index = @atomicLoad(usize, &node.end_index, .monotonic); |
| 609 | while (true) { | 599 | if (buf_ptr + cur_end_index != memory.ptr + memory.len) { |
| 610 | if (cur_buf_ptr + cur_end_index != buf.ptr + buf.len) { | 600 | // Not the most recent allocation; we cannot free it. |
| 611 | // Not the most recent allocation; we cannot free it. | 601 | return; |
| 612 | return; | | |
| 613 | } | | |
| 614 | const new_end_index = cur_end_index - buf.len; | | |
| 615 | | | |
| 616 | cur_end_index = @cmpxchgWeak( | | |
| 617 | usize, | | |
| 618 | &node.end_index, | | |
| 619 | cur_end_index, | | |
| 620 | new_end_index, | | |
| 621 | .monotonic, | | |
| 622 | .monotonic, | | |
| 623 | ) orelse { | | |
| 624 | return; | | |
| 625 | }; | | |
| 626 | } | 602 | } |
| | 603 | |
| | 604 | const new_end_index = cur_end_index - memory.len; |
| | 605 | assert(buf_ptr + new_end_index == memory.ptr); |
| | 606 | |
| | 607 | _ = @cmpxchgStrong( |
| | 608 | usize, |
| | 609 | &node.end_index, |
| | 610 | cur_end_index, |
| | 611 | new_end_index, |
| | 612 | .monotonic, |
| | 613 | .monotonic, |
| | 614 | ); |
| 627 | } | 615 | } |
| 628 | | 616 | |
| 629 | const std = @import("std"); | 617 | const std = @import("std"); |