| author | |
| committer | |
| log | 066eaa5e9cbfde172449f6d95bb884c7d86ac10c |
| tree | 7829767fd8b421f6a1c58798692f45ebec43746d |
| parent | f68cda738ad0d3e9bc0f328befad301d9e23756e |
| signature |
15 files changed, 112 insertions(+), 196 deletions(-)
lib/std/build/OptionsStep.zig+1-1| ... | @@ -350,5 +350,5 @@ test "OptionsStep" { | ... | @@ -350,5 +350,5 @@ test "OptionsStep" { |
| 350 | \\ | 350 | \\ |
| 351 | , options.contents.items); | 351 | , options.contents.items); |
| 352 | 352 | ||
| 353 | _ = try std.zig.parse(&arena.allocator, try options.contents.toOwnedSliceSentinel(0)); | 353 | _ = try std.zig.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0)); |
| 354 | } | 354 | } |
lib/std/heap.zig+16-18| ... | @@ -129,7 +129,7 @@ const CAllocator = struct { | ... | @@ -129,7 +129,7 @@ const CAllocator = struct { |
| 129 | new_len: usize, | 129 | new_len: usize, |
| 130 | len_align: u29, | 130 | len_align: u29, |
| 131 | return_address: usize, | 131 | return_address: usize, |
| 132 | ) Allocator.Error!usize { | 132 | ) ?usize { |
| 133 | _ = buf_align; | 133 | _ = buf_align; |
| 134 | _ = return_address; | 134 | _ = return_address; |
| 135 | if (new_len <= buf.len) { | 135 | if (new_len <= buf.len) { |
| ... | @@ -141,7 +141,7 @@ const CAllocator = struct { | ... | @@ -141,7 +141,7 @@ const CAllocator = struct { |
| 141 | return mem.alignAllocLen(full_len, new_len, len_align); | 141 | return mem.alignAllocLen(full_len, new_len, len_align); |
| 142 | } | 142 | } |
| 143 | } | 143 | } |
| 144 | return error.OutOfMemory; | 144 | return null; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | fn free( | 147 | fn free( |
| ... | @@ -205,13 +205,13 @@ fn rawCResize( | ... | @@ -205,13 +205,13 @@ fn rawCResize( |
| 205 | new_len: usize, | 205 | new_len: usize, |
| 206 | len_align: u29, | 206 | len_align: u29, |
| 207 | ret_addr: usize, | 207 | ret_addr: usize, |
| 208 | ) Allocator.Error!usize { | 208 | ) ?usize { |
| 209 | _ = old_align; | 209 | _ = old_align; |
| 210 | _ = ret_addr; | 210 | _ = ret_addr; |
| 211 | if (new_len <= buf.len) { | 211 | if (new_len <= buf.len) { |
| 212 | return mem.alignAllocLen(buf.len, new_len, len_align); | 212 | return mem.alignAllocLen(buf.len, new_len, len_align); |
| 213 | } | 213 | } |
| 214 | return error.OutOfMemory; | 214 | return null; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | fn rawCFree( | 217 | fn rawCFree( |
| ... | @@ -361,7 +361,7 @@ const PageAllocator = struct { | ... | @@ -361,7 +361,7 @@ const PageAllocator = struct { |
| 361 | new_size: usize, | 361 | new_size: usize, |
| 362 | len_align: u29, | 362 | len_align: u29, |
| 363 | return_address: usize, | 363 | return_address: usize, |
| 364 | ) Allocator.Error!usize { | 364 | ) ?usize { |
| 365 | _ = buf_align; | 365 | _ = buf_align; |
| 366 | _ = return_address; | 366 | _ = return_address; |
| 367 | const new_size_aligned = mem.alignForward(new_size, mem.page_size); | 367 | const new_size_aligned = mem.alignForward(new_size, mem.page_size); |
| ... | @@ -387,7 +387,7 @@ const PageAllocator = struct { | ... | @@ -387,7 +387,7 @@ const PageAllocator = struct { |
| 387 | if (new_size_aligned <= old_size_aligned) { | 387 | if (new_size_aligned <= old_size_aligned) { |
| 388 | return alignPageAllocLen(new_size_aligned, new_size, len_align); | 388 | return alignPageAllocLen(new_size_aligned, new_size, len_align); |
| 389 | } | 389 | } |
| 390 | return error.OutOfMemory; | 390 | return null; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | const buf_aligned_len = mem.alignForward(buf_unaligned.len, mem.page_size); | 393 | const buf_aligned_len = mem.alignForward(buf_unaligned.len, mem.page_size); |
| ... | @@ -403,7 +403,7 @@ const PageAllocator = struct { | ... | @@ -403,7 +403,7 @@ const PageAllocator = struct { |
| 403 | 403 | ||
| 404 | // TODO: call mremap | 404 | // TODO: call mremap |
| 405 | // TODO: if the next_mmap_addr_hint is within the remapped range, update it | 405 | // TODO: if the next_mmap_addr_hint is within the remapped range, update it |
| 406 | return error.OutOfMemory; | 406 | return null; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | fn free(_: *c_void, buf_unaligned: []u8, buf_align: u29, return_address: usize) void { | 409 | fn free(_: *c_void, buf_unaligned: []u8, buf_align: u29, return_address: usize) void { |
| ... | @@ -579,11 +579,11 @@ const WasmPageAllocator = struct { | ... | @@ -579,11 +579,11 @@ const WasmPageAllocator = struct { |
| 579 | new_len: usize, | 579 | new_len: usize, |
| 580 | len_align: u29, | 580 | len_align: u29, |
| 581 | return_address: usize, | 581 | return_address: usize, |
| 582 | ) error{OutOfMemory}!usize { | 582 | ) ?usize { |
| 583 | _ = buf_align; | 583 | _ = buf_align; |
| 584 | _ = return_address; | 584 | _ = return_address; |
| 585 | const aligned_len = mem.alignForward(buf.len, mem.page_size); | 585 | const aligned_len = mem.alignForward(buf.len, mem.page_size); |
| 586 | if (new_len > aligned_len) return error.OutOfMemory; | 586 | if (new_len > aligned_len) return null; |
| 587 | const current_n = nPages(aligned_len); | 587 | const current_n = nPages(aligned_len); |
| 588 | const new_n = nPages(new_len); | 588 | const new_n = nPages(new_len); |
| 589 | if (new_n != current_n) { | 589 | if (new_n != current_n) { |
| ... | @@ -674,7 +674,7 @@ pub const HeapAllocator = switch (builtin.os.tag) { | ... | @@ -674,7 +674,7 @@ pub const HeapAllocator = switch (builtin.os.tag) { |
| 674 | new_size: usize, | 674 | new_size: usize, |
| 675 | len_align: u29, | 675 | len_align: u29, |
| 676 | return_address: usize, | 676 | return_address: usize, |
| 677 | ) error{OutOfMemory}!usize { | 677 | ) ?usize { |
| 678 | _ = buf_align; | 678 | _ = buf_align; |
| 679 | _ = return_address; | 679 | _ = return_address; |
| 680 | 680 | ||
| ... | @@ -686,7 +686,7 @@ pub const HeapAllocator = switch (builtin.os.tag) { | ... | @@ -686,7 +686,7 @@ pub const HeapAllocator = switch (builtin.os.tag) { |
| 686 | os.windows.HEAP_REALLOC_IN_PLACE_ONLY, | 686 | os.windows.HEAP_REALLOC_IN_PLACE_ONLY, |
| 687 | @intToPtr(*c_void, root_addr), | 687 | @intToPtr(*c_void, root_addr), |
| 688 | amt, | 688 | amt, |
| 689 | ) orelse return error.OutOfMemory; | 689 | ) orelse return null; |
| 690 | assert(new_ptr == @intToPtr(*c_void, root_addr)); | 690 | assert(new_ptr == @intToPtr(*c_void, root_addr)); |
| 691 | const return_len = init: { | 691 | const return_len = init: { |
| 692 | if (len_align == 0) break :init new_size; | 692 | if (len_align == 0) break :init new_size; |
| ... | @@ -788,14 +788,13 @@ pub const FixedBufferAllocator = struct { | ... | @@ -788,14 +788,13 @@ pub const FixedBufferAllocator = struct { |
| 788 | new_size: usize, | 788 | new_size: usize, |
| 789 | len_align: u29, | 789 | len_align: u29, |
| 790 | return_address: usize, | 790 | return_address: usize, |
| 791 | ) Allocator.Error!usize { | 791 | ) ?usize { |
| 792 | _ = buf_align; | 792 | _ = buf_align; |
| 793 | _ = return_address; | 793 | _ = return_address; |
| 794 | assert(self.ownsSlice(buf)); // sanity check | 794 | assert(self.ownsSlice(buf)); // sanity check |
| 795 | 795 | ||
| 796 | if (!self.isLastAllocation(buf)) { | 796 | if (!self.isLastAllocation(buf)) { |
| 797 | if (new_size > buf.len) | 797 | if (new_size > buf.len) return null; |
| 798 | return error.OutOfMemory; | ||
| 799 | return mem.alignAllocLen(buf.len, new_size, len_align); | 798 | return mem.alignAllocLen(buf.len, new_size, len_align); |
| 800 | } | 799 | } |
| 801 | 800 | ||
| ... | @@ -806,9 +805,8 @@ pub const FixedBufferAllocator = struct { | ... | @@ -806,9 +805,8 @@ pub const FixedBufferAllocator = struct { |
| 806 | } | 805 | } |
| 807 | 806 | ||
| 808 | const add = new_size - buf.len; | 807 | const add = new_size - buf.len; |
| 809 | if (add + self.end_index > self.buffer.len) { | 808 | if (add + self.end_index > self.buffer.len) return null; |
| 810 | return error.OutOfMemory; | 809 | |
| 811 | } | ||
| 812 | self.end_index += add; | 810 | self.end_index += add; |
| 813 | return new_size; | 811 | return new_size; |
| 814 | } | 812 | } |
| ... | @@ -891,7 +889,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type { | ... | @@ -891,7 +889,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type { |
| 891 | new_len: usize, | 889 | new_len: usize, |
| 892 | len_align: u29, | 890 | len_align: u29, |
| 893 | return_address: usize, | 891 | return_address: usize, |
| 894 | ) error{OutOfMemory}!usize { | 892 | ) ?usize { |
| 895 | if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) { | 893 | if (self.fixed_buffer_allocator.ownsPtr(buf.ptr)) { |
| 896 | return FixedBufferAllocator.resize(&self.fixed_buffer_allocator, buf, buf_align, new_len, len_align, return_address); | 894 | return FixedBufferAllocator.resize(&self.fixed_buffer_allocator, buf, buf_align, new_len, len_align, return_address); |
| 897 | } else { | 895 | } else { |
lib/std/heap/arena_allocator.zig+8-11| ... | @@ -78,26 +78,23 @@ pub const ArenaAllocator = struct { | ... | @@ -78,26 +78,23 @@ pub const ArenaAllocator = struct { |
| 78 | 78 | ||
| 79 | const bigger_buf_size = @sizeOf(BufNode) + new_end_index; | 79 | const bigger_buf_size = @sizeOf(BufNode) + new_end_index; |
| 80 | // Try to grow the buffer in-place | 80 | // Try to grow the buffer in-place |
| 81 | cur_node.data = self.child_allocator.resize(cur_node.data, bigger_buf_size) catch |err| switch (err) { | 81 | cur_node.data = self.child_allocator.resize(cur_node.data, bigger_buf_size) orelse { |
| 82 | error.OutOfMemory => { | 82 | // Allocate a new node if that's not possible |
| 83 | // Allocate a new node if that's not possible | 83 | cur_node = try self.createNode(cur_buf.len, n + ptr_align); |
| 84 | cur_node = try self.createNode(cur_buf.len, n + ptr_align); | 84 | continue; |
| 85 | continue; | ||
| 86 | }, | ||
| 87 | }; | 85 | }; |
| 88 | } | 86 | } |
| 89 | } | 87 | } |
| 90 | 88 | ||
| 91 | fn resize(self: *ArenaAllocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) Allocator.Error!usize { | 89 | fn resize(self: *ArenaAllocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize { |
| 92 | _ = buf_align; | 90 | _ = buf_align; |
| 93 | _ = len_align; | 91 | _ = len_align; |
| 94 | _ = ret_addr; | 92 | _ = ret_addr; |
| 95 | 93 | ||
| 96 | const cur_node = self.state.buffer_list.first orelse return error.OutOfMemory; | 94 | const cur_node = self.state.buffer_list.first orelse return null; |
| 97 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; | 95 | const cur_buf = cur_node.data[@sizeOf(BufNode)..]; |
| 98 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index != @ptrToInt(buf.ptr) + buf.len) { | 96 | if (@ptrToInt(cur_buf.ptr) + self.state.end_index != @ptrToInt(buf.ptr) + buf.len) { |
| 99 | if (new_len > buf.len) | 97 | if (new_len > buf.len) return null; |
| 100 | return error.OutOfMemory; | ||
| 101 | return new_len; | 98 | return new_len; |
| 102 | } | 99 | } |
| 103 | 100 | ||
| ... | @@ -108,7 +105,7 @@ pub const ArenaAllocator = struct { | ... | @@ -108,7 +105,7 @@ pub const ArenaAllocator = struct { |
| 108 | self.state.end_index += new_len - buf.len; | 105 | self.state.end_index += new_len - buf.len; |
| 109 | return new_len; | 106 | return new_len; |
| 110 | } else { | 107 | } else { |
| 111 | return error.OutOfMemory; | 108 | return null; |
| 112 | } | 109 | } |
| 113 | } | 110 | } |
| 114 | 111 |
lib/std/heap/general_purpose_allocator.zig+10-10| ... | @@ -517,7 +517,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -517,7 +517,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 517 | new_size: usize, | 517 | new_size: usize, |
| 518 | len_align: u29, | 518 | len_align: u29, |
| 519 | ret_addr: usize, | 519 | ret_addr: usize, |
| 520 | ) Error!usize { | 520 | ) ?usize { |
| 521 | const entry = self.large_allocations.getEntry(@ptrToInt(old_mem.ptr)) orelse { | 521 | const entry = self.large_allocations.getEntry(@ptrToInt(old_mem.ptr)) orelse { |
| 522 | if (config.safety) { | 522 | if (config.safety) { |
| 523 | @panic("Invalid free"); | 523 | @panic("Invalid free"); |
| ... | @@ -557,7 +557,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -557,7 +557,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 557 | if (config.enable_memory_limit) { | 557 | if (config.enable_memory_limit) { |
| 558 | const new_req_bytes = prev_req_bytes + new_size - entry.value_ptr.requested_size; | 558 | const new_req_bytes = prev_req_bytes + new_size - entry.value_ptr.requested_size; |
| 559 | if (new_req_bytes > prev_req_bytes and new_req_bytes > self.requested_memory_limit) { | 559 | if (new_req_bytes > prev_req_bytes and new_req_bytes > self.requested_memory_limit) { |
| 560 | return error.OutOfMemory; | 560 | return null; |
| 561 | } | 561 | } |
| 562 | self.total_requested_bytes = new_req_bytes; | 562 | self.total_requested_bytes = new_req_bytes; |
| 563 | } | 563 | } |
| ... | @@ -565,7 +565,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -565,7 +565,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 565 | self.total_requested_bytes = prev_req_bytes; | 565 | self.total_requested_bytes = prev_req_bytes; |
| 566 | }; | 566 | }; |
| 567 | 567 | ||
| 568 | const result_len = try self.backing_allocator.rawResize(old_mem, old_align, new_size, len_align, ret_addr); | 568 | const result_len = self.backing_allocator.rawResize(old_mem, old_align, new_size, len_align, ret_addr) orelse return null; |
| 569 | 569 | ||
| 570 | if (config.enable_memory_limit) { | 570 | if (config.enable_memory_limit) { |
| 571 | entry.value_ptr.requested_size = new_size; | 571 | entry.value_ptr.requested_size = new_size; |
| ... | @@ -650,7 +650,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -650,7 +650,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 650 | new_size: usize, | 650 | new_size: usize, |
| 651 | len_align: u29, | 651 | len_align: u29, |
| 652 | ret_addr: usize, | 652 | ret_addr: usize, |
| 653 | ) Error!usize { | 653 | ) ?usize { |
| 654 | self.mutex.lock(); | 654 | self.mutex.lock(); |
| 655 | defer self.mutex.unlock(); | 655 | defer self.mutex.unlock(); |
| 656 | 656 | ||
| ... | @@ -705,7 +705,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -705,7 +705,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 705 | if (config.enable_memory_limit) { | 705 | if (config.enable_memory_limit) { |
| 706 | const new_req_bytes = prev_req_bytes + new_size - old_mem.len; | 706 | const new_req_bytes = prev_req_bytes + new_size - old_mem.len; |
| 707 | if (new_req_bytes > prev_req_bytes and new_req_bytes > self.requested_memory_limit) { | 707 | if (new_req_bytes > prev_req_bytes and new_req_bytes > self.requested_memory_limit) { |
| 708 | return error.OutOfMemory; | 708 | return null; |
| 709 | } | 709 | } |
| 710 | self.total_requested_bytes = new_req_bytes; | 710 | self.total_requested_bytes = new_req_bytes; |
| 711 | } | 711 | } |
| ... | @@ -726,7 +726,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -726,7 +726,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 726 | } | 726 | } |
| 727 | return new_size; | 727 | return new_size; |
| 728 | } | 728 | } |
| 729 | return error.OutOfMemory; | 729 | return null; |
| 730 | } | 730 | } |
| 731 | 731 | ||
| 732 | fn free( | 732 | fn free( |
| ... | @@ -735,8 +735,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -735,8 +735,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 735 | old_align: u29, | 735 | old_align: u29, |
| 736 | ret_addr: usize, | 736 | ret_addr: usize, |
| 737 | ) void { | 737 | ) void { |
| 738 | const held = self.mutex.acquire(); | 738 | self.mutex.lock(); |
| 739 | defer held.release(); | 739 | defer self.mutex.unlock(); |
| 740 | 740 | ||
| 741 | assert(old_mem.len != 0); | 741 | assert(old_mem.len != 0); |
| 742 | 742 | ||
| ... | @@ -850,7 +850,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -850,7 +850,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 850 | return true; | 850 | return true; |
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | fn alloc(self: Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8 { | 853 | fn alloc(self: *Self, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8 { |
| 854 | self.mutex.lock(); | 854 | self.mutex.lock(); |
| 855 | defer self.mutex.unlock(); | 855 | defer self.mutex.unlock(); |
| 856 | 856 | ||
| ... | @@ -1065,7 +1065,7 @@ test "shrink large object to large object" { | ... | @@ -1065,7 +1065,7 @@ test "shrink large object to large object" { |
| 1065 | slice[0] = 0x12; | 1065 | slice[0] = 0x12; |
| 1066 | slice[60] = 0x34; | 1066 | slice[60] = 0x34; |
| 1067 | 1067 | ||
| 1068 | slice = try allocator.resize(slice, page_size * 2 + 1); | 1068 | slice = allocator.resize(slice, page_size * 2 + 1) orelse return; |
| 1069 | try std.testing.expect(slice[0] == 0x12); | 1069 | try std.testing.expect(slice[0] == 0x12); |
| 1070 | try std.testing.expect(slice[60] == 0x34); | 1070 | try std.testing.expect(slice[60] == 0x34); |
| 1071 | 1071 |
lib/std/heap/log_to_writer_allocator.zig+7-6| ... | @@ -45,22 +45,23 @@ pub fn LogToWriterAllocator(comptime Writer: type) type { | ... | @@ -45,22 +45,23 @@ pub fn LogToWriterAllocator(comptime Writer: type) type { |
| 45 | new_len: usize, | 45 | new_len: usize, |
| 46 | len_align: u29, | 46 | len_align: u29, |
| 47 | ra: usize, | 47 | ra: usize, |
| 48 | ) error{OutOfMemory}!usize { | 48 | ) ?usize { |
| 49 | if (new_len <= buf.len) { | 49 | if (new_len <= buf.len) { |
| 50 | self.writer.print("shrink: {} to {}\n", .{ buf.len, new_len }) catch {}; | 50 | self.writer.print("shrink: {} to {}\n", .{ buf.len, new_len }) catch {}; |
| 51 | } else { | 51 | } else { |
| 52 | self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {}; | 52 | self.writer.print("expand: {} to {}", .{ buf.len, new_len }) catch {}; |
| 53 | } | 53 | } |
| 54 | |||
| 54 | if (self.parent_allocator.rawResize(buf, buf_align, new_len, len_align, ra)) |resized_len| { | 55 | if (self.parent_allocator.rawResize(buf, buf_align, new_len, len_align, ra)) |resized_len| { |
| 55 | if (new_len > buf.len) { | 56 | if (new_len > buf.len) { |
| 56 | self.writer.print(" success!\n", .{}) catch {}; | 57 | self.writer.print(" success!\n", .{}) catch {}; |
| 57 | } | 58 | } |
| 58 | return resized_len; | 59 | return resized_len; |
| 59 | } else |e| { | ||
| 60 | std.debug.assert(new_len > buf.len); | ||
| 61 | self.writer.print(" failure!\n", .{}) catch {}; | ||
| 62 | return e; | ||
| 63 | } | 60 | } |
| 61 | |||
| 62 | std.debug.assert(new_len > buf.len); | ||
| 63 | self.writer.print(" failure!\n", .{}) catch {}; | ||
| 64 | return null; | ||
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | fn free( | 67 | fn free( |
| ... | @@ -95,7 +96,7 @@ test "LogToWriterAllocator" { | ... | @@ -95,7 +96,7 @@ test "LogToWriterAllocator" { |
| 95 | var a = try allocator.alloc(u8, 10); | 96 | var a = try allocator.alloc(u8, 10); |
| 96 | a = allocator.shrink(a, 5); | 97 | a = allocator.shrink(a, 5); |
| 97 | try std.testing.expect(a.len == 5); | 98 | try std.testing.expect(a.len == 5); |
| 98 | try std.testing.expectError(error.OutOfMemory, allocator.resize(a, 20)); | 99 | try std.testing.expect(allocator.resize(a, 20) == null); |
| 99 | allocator.free(a); | 100 | allocator.free(a); |
| 100 | 101 | ||
| 101 | try std.testing.expectEqualSlices(u8, | 102 | try std.testing.expectEqualSlices(u8, |
lib/std/heap/logging_allocator.zig+9-9| ... | @@ -77,7 +77,7 @@ pub fn ScopedLoggingAllocator( | ... | @@ -77,7 +77,7 @@ pub fn ScopedLoggingAllocator( |
| 77 | new_len: usize, | 77 | new_len: usize, |
| 78 | len_align: u29, | 78 | len_align: u29, |
| 79 | ra: usize, | 79 | ra: usize, |
| 80 | ) error{OutOfMemory}!usize { | 80 | ) ?usize { |
| 81 | if (self.parent_allocator.rawResize(buf, buf_align, new_len, len_align, ra)) |resized_len| { | 81 | if (self.parent_allocator.rawResize(buf, buf_align, new_len, len_align, ra)) |resized_len| { |
| 82 | if (new_len <= buf.len) { | 82 | if (new_len <= buf.len) { |
| 83 | logHelper( | 83 | logHelper( |
| ... | @@ -94,15 +94,15 @@ pub fn ScopedLoggingAllocator( | ... | @@ -94,15 +94,15 @@ pub fn ScopedLoggingAllocator( |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | return resized_len; | 96 | return resized_len; |
| 97 | } else |err| { | ||
| 98 | std.debug.assert(new_len > buf.len); | ||
| 99 | logHelper( | ||
| 100 | failure_log_level, | ||
| 101 | "expand - failure: {s} - {} to {}, len_align: {}, buf_align: {}", | ||
| 102 | .{ @errorName(err), buf.len, new_len, len_align, buf_align }, | ||
| 103 | ); | ||
| 104 | return err; | ||
| 105 | } | 97 | } |
| 98 | |||
| 99 | std.debug.assert(new_len > buf.len); | ||
| 100 | logHelper( | ||
| 101 | failure_log_level, | ||
| 102 | "expand - failure - {} to {}, len_align: {}, buf_align: {}", | ||
| 103 | .{ buf.len, new_len, len_align, buf_align }, | ||
| 104 | ); | ||
| 105 | return null; | ||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | fn free( | 108 | fn free( |
lib/std/mem.zig+4-4| ... | @@ -88,14 +88,14 @@ pub fn ValidationAllocator(comptime T: type) type { | ... | @@ -88,14 +88,14 @@ pub fn ValidationAllocator(comptime T: type) type { |
| 88 | new_len: usize, | 88 | new_len: usize, |
| 89 | len_align: u29, | 89 | len_align: u29, |
| 90 | ret_addr: usize, | 90 | ret_addr: usize, |
| 91 | ) Allocator.Error!usize { | 91 | ) ?usize { |
| 92 | assert(buf.len > 0); | 92 | assert(buf.len > 0); |
| 93 | if (len_align != 0) { | 93 | if (len_align != 0) { |
| 94 | assert(mem.isAlignedAnyAlign(new_len, len_align)); | 94 | assert(mem.isAlignedAnyAlign(new_len, len_align)); |
| 95 | assert(new_len >= len_align); | 95 | assert(new_len >= len_align); |
| 96 | } | 96 | } |
| 97 | const underlying = self.getUnderlyingAllocatorPtr(); | 97 | const underlying = self.getUnderlyingAllocatorPtr(); |
| 98 | const result = try underlying.rawResize(buf, buf_align, new_len, len_align, ret_addr); | 98 | const result = underlying.rawResize(buf, buf_align, new_len, len_align, ret_addr) orelse return null; |
| 99 | if (len_align == 0) { | 99 | if (len_align == 0) { |
| 100 | assert(result == new_len); | 100 | assert(result == new_len); |
| 101 | } else { | 101 | } else { |
| ... | @@ -188,7 +188,7 @@ test "Allocator.resize" { | ... | @@ -188,7 +188,7 @@ test "Allocator.resize" { |
| 188 | defer testing.allocator.free(values); | 188 | defer testing.allocator.free(values); |
| 189 | 189 | ||
| 190 | for (values) |*v, i| v.* = @intCast(T, i); | 190 | for (values) |*v, i| v.* = @intCast(T, i); |
| 191 | values = try testing.allocator.resize(values, values.len + 10); | 191 | values = testing.allocator.resize(values, values.len + 10) orelse return error.OutOfMemory; |
| 192 | try testing.expect(values.len == 110); | 192 | try testing.expect(values.len == 110); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| ... | @@ -203,7 +203,7 @@ test "Allocator.resize" { | ... | @@ -203,7 +203,7 @@ test "Allocator.resize" { |
| 203 | defer testing.allocator.free(values); | 203 | defer testing.allocator.free(values); |
| 204 | 204 | ||
| 205 | for (values) |*v, i| v.* = @intToFloat(T, i); | 205 | for (values) |*v, i| v.* = @intToFloat(T, i); |
| 206 | values = try testing.allocator.resize(values, values.len + 10); | 206 | values = testing.allocator.resize(values, values.len + 10) orelse return error.OutOfMemory; |
| 207 | try testing.expect(values.len == 110); | 207 | try testing.expect(values.len == 110); |
| 208 | } | 208 | } |
| 209 | } | 209 | } |
lib/std/mem/Allocator.zig+38-110| ... | @@ -29,9 +29,9 @@ pub const VTable = struct { | ... | @@ -29,9 +29,9 @@ pub const VTable = struct { |
| 29 | /// length returned by `alloc` or `resize`. `buf_align` must equal the same value | 29 | /// length returned by `alloc` or `resize`. `buf_align` must equal the same value |
| 30 | /// that was passed as the `ptr_align` parameter to the original `alloc` call. | 30 | /// that was passed as the `ptr_align` parameter to the original `alloc` call. |
| 31 | /// | 31 | /// |
| 32 | /// error.OutOfMemory can only be returned if `new_len` is greater than `buf.len`. | 32 | /// `null` can only be returned if `new_len` is greater than `buf.len`. |
| 33 | /// If `buf` cannot be expanded to accomodate `new_len`, then the allocation MUST be | 33 | /// If `buf` cannot be expanded to accomodate `new_len`, then the allocation MUST be |
| 34 | /// unmodified and error.OutOfMemory MUST be returned. | 34 | /// unmodified and `null` MUST be returned. |
| 35 | /// | 35 | /// |
| 36 | /// If `len_align` is `0`, then the length returned MUST be exactly `len` bytes, | 36 | /// If `len_align` is `0`, then the length returned MUST be exactly `len` bytes, |
| 37 | /// otherwise, the length must be aligned to `len_align`. Note that `len_align` does *not* | 37 | /// otherwise, the length must be aligned to `len_align`. Note that `len_align` does *not* |
| ... | @@ -42,7 +42,7 @@ pub const VTable = struct { | ... | @@ -42,7 +42,7 @@ pub const VTable = struct { |
| 42 | /// | 42 | /// |
| 43 | /// `ret_addr` is optionally provided as the first return address of the allocation call stack. | 43 | /// `ret_addr` is optionally provided as the first return address of the allocation call stack. |
| 44 | /// If the value is `0` it means no return address has been provided. | 44 | /// If the value is `0` it means no return address has been provided. |
| 45 | resize: fn (ptr: *c_void, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) Error!usize, | 45 | resize: fn (ptr: *c_void, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize, |
| 46 | 46 | ||
| 47 | /// Free and invalidate a buffer. `buf.len` must equal the most recent length returned by `alloc` or `resize`. | 47 | /// Free and invalidate a buffer. `buf.len` must equal the most recent length returned by `alloc` or `resize`. |
| 48 | /// `buf_align` must equal the same value that was passed as the `ptr_align` parameter to the original `alloc` call. | 48 | /// `buf_align` must equal the same value that was passed as the `ptr_align` parameter to the original `alloc` call. |
| ... | @@ -55,7 +55,7 @@ pub const VTable = struct { | ... | @@ -55,7 +55,7 @@ pub const VTable = struct { |
| 55 | pub fn init( | 55 | pub fn init( |
| 56 | pointer: anytype, | 56 | pointer: anytype, |
| 57 | comptime allocFn: fn (ptr: @TypeOf(pointer), len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8, | 57 | comptime allocFn: fn (ptr: @TypeOf(pointer), len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8, |
| 58 | comptime resizeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) Error!usize, | 58 | comptime resizeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize, |
| 59 | comptime freeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, ret_addr: usize) void, | 59 | comptime freeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, ret_addr: usize) void, |
| 60 | ) Allocator { | 60 | ) Allocator { |
| 61 | const Ptr = @TypeOf(pointer); | 61 | const Ptr = @TypeOf(pointer); |
| ... | @@ -71,7 +71,7 @@ pub fn init( | ... | @@ -71,7 +71,7 @@ pub fn init( |
| 71 | const self = @ptrCast(Ptr, @alignCast(alignment, ptr)); | 71 | const self = @ptrCast(Ptr, @alignCast(alignment, ptr)); |
| 72 | return @call(.{ .modifier = .always_inline }, allocFn, .{ self, len, ptr_align, len_align, ret_addr }); | 72 | return @call(.{ .modifier = .always_inline }, allocFn, .{ self, len, ptr_align, len_align, ret_addr }); |
| 73 | } | 73 | } |
| 74 | fn resize(ptr: *c_void, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) Error!usize { | 74 | fn resize(ptr: *c_void, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize { |
| 75 | assert(new_len != 0); | 75 | assert(new_len != 0); |
| 76 | const self = @ptrCast(Ptr, @alignCast(alignment, ptr)); | 76 | const self = @ptrCast(Ptr, @alignCast(alignment, ptr)); |
| 77 | return @call(.{ .modifier = .always_inline }, resizeFn, .{ self, buf, buf_align, new_len, len_align, ret_addr }); | 77 | return @call(.{ .modifier = .always_inline }, resizeFn, .{ self, buf, buf_align, new_len, len_align, ret_addr }); |
| ... | @@ -104,14 +104,12 @@ pub fn NoResize(comptime AllocatorType: type) type { | ... | @@ -104,14 +104,12 @@ pub fn NoResize(comptime AllocatorType: type) type { |
| 104 | new_len: usize, | 104 | new_len: usize, |
| 105 | len_align: u29, | 105 | len_align: u29, |
| 106 | ret_addr: usize, | 106 | ret_addr: usize, |
| 107 | ) Error!usize { | 107 | ) ?usize { |
| 108 | _ = self; | 108 | _ = self; |
| 109 | _ = buf_align; | 109 | _ = buf_align; |
| 110 | _ = len_align; | 110 | _ = len_align; |
| 111 | _ = ret_addr; | 111 | _ = ret_addr; |
| 112 | if (new_len > buf.len) | 112 | return if (new_len > buf.len) null else new_len; |
| 113 | return error.OutOfMemory; | ||
| 114 | return new_len; | ||
| 115 | } | 113 | } |
| 116 | }; | 114 | }; |
| 117 | } | 115 | } |
| ... | @@ -157,7 +155,7 @@ pub inline fn rawAlloc(self: Allocator, len: usize, ptr_align: u29, len_align: u | ... | @@ -157,7 +155,7 @@ pub inline fn rawAlloc(self: Allocator, len: usize, ptr_align: u29, len_align: u |
| 157 | } | 155 | } |
| 158 | 156 | ||
| 159 | /// This function is not intended to be called except from within the implementation of an Allocator | 157 | /// This function is not intended to be called except from within the implementation of an Allocator |
| 160 | pub inline fn rawResize(self: Allocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) Error!usize { | 158 | pub inline fn rawResize(self: Allocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize { |
| 161 | return self.vtable.resize(self.ptr, buf, buf_align, new_len, len_align, ret_addr); | 159 | return self.vtable.resize(self.ptr, buf, buf_align, new_len, len_align, ret_addr); |
| 162 | } | 160 | } |
| 163 | 161 | ||
| ... | @@ -166,99 +164,6 @@ pub inline fn rawFree(self: Allocator, buf: []u8, buf_align: u29, ret_addr: usiz | ... | @@ -166,99 +164,6 @@ pub inline fn rawFree(self: Allocator, buf: []u8, buf_align: u29, ret_addr: usiz |
| 166 | return self.vtable.free(self.ptr, buf, buf_align, ret_addr); | 164 | return self.vtable.free(self.ptr, buf, buf_align, ret_addr); |
| 167 | } | 165 | } |
| 168 | 166 | ||
| 169 | /// Realloc is used to modify the size or alignment of an existing allocation, | ||
| 170 | /// as well as to provide the allocator with an opportunity to move an allocation | ||
| 171 | /// to a better location. | ||
| 172 | /// When the size/alignment is greater than the previous allocation, this function | ||
| 173 | /// returns `error.OutOfMemory` when the requested new allocation could not be granted. | ||
| 174 | /// When the size/alignment is less than or equal to the previous allocation, | ||
| 175 | /// this function returns `error.OutOfMemory` when the allocator decides the client | ||
| 176 | /// would be better off keeping the extra alignment/size. Clients will call | ||
| 177 | /// `vtable.resize` when they require the allocator to track a new alignment/size, | ||
| 178 | /// and so this function should only return success when the allocator considers | ||
| 179 | /// the reallocation desirable from the allocator's perspective. | ||
| 180 | /// As an example, `std.ArrayList` tracks a "capacity", and therefore can handle | ||
| 181 | /// reallocation failure, even when `new_n` <= `old_mem.len`. A `FixedBufferAllocator` | ||
| 182 | /// would always return `error.OutOfMemory` for `reallocFn` when the size/alignment | ||
| 183 | /// is less than or equal to the old allocation, because it cannot reclaim the memory, | ||
| 184 | /// and thus the `std.ArrayList` would be better off retaining its capacity. | ||
| 185 | /// When `reallocFn` returns, | ||
| 186 | /// `return_value[0..min(old_mem.len, new_byte_count)]` must be the same | ||
| 187 | /// as `old_mem` was when `reallocFn` is called. The bytes of | ||
| 188 | /// `return_value[old_mem.len..]` have undefined values. | ||
| 189 | /// The returned slice must have its pointer aligned at least to `new_alignment` bytes. | ||
| 190 | fn reallocBytes( | ||
| 191 | self: Allocator, | ||
| 192 | /// Guaranteed to be the same as what was returned from most recent call to | ||
| 193 | /// `vtable.alloc` or `vtable.resize`. | ||
| 194 | /// If `old_mem.len == 0` then this is a new allocation and `new_byte_count` | ||
| 195 | /// is guaranteed to be >= 1. | ||
| 196 | old_mem: []u8, | ||
| 197 | /// If `old_mem.len == 0` then this is `undefined`, otherwise: | ||
| 198 | /// Guaranteed to be the same as what was passed to `allocFn`. | ||
| 199 | /// Guaranteed to be >= 1. | ||
| 200 | /// Guaranteed to be a power of 2. | ||
| 201 | old_alignment: u29, | ||
| 202 | /// `new_byte_count` must be greater than zero | ||
| 203 | new_byte_count: usize, | ||
| 204 | /// Guaranteed to be >= 1. | ||
| 205 | /// Guaranteed to be a power of 2. | ||
| 206 | /// Returned slice's pointer must have this alignment. | ||
| 207 | new_alignment: u29, | ||
| 208 | /// 0 indicates the length of the slice returned MUST match `new_byte_count` exactly | ||
| 209 | /// non-zero means the length of the returned slice must be aligned by `len_align` | ||
| 210 | /// `new_len` must be aligned by `len_align` | ||
| 211 | len_align: u29, | ||
| 212 | return_address: usize, | ||
| 213 | ) Error![]u8 { | ||
| 214 | if (old_mem.len == 0) { | ||
| 215 | const new_mem = try self.rawAlloc(new_byte_count, new_alignment, len_align, return_address); | ||
| 216 | // TODO: https://github.com/ziglang/zig/issues/4298 | ||
| 217 | @memset(new_mem.ptr, undefined, new_byte_count); | ||
| 218 | return new_mem; | ||
| 219 | } | ||
| 220 | |||
| 221 | assert(new_byte_count > 0); // `new_byte_count` must greater than zero, this is a resize not a free | ||
| 222 | |||
| 223 | if (mem.isAligned(@ptrToInt(old_mem.ptr), new_alignment)) { | ||
| 224 | if (new_byte_count <= old_mem.len) { | ||
| 225 | const shrunk_len = self.shrinkBytes(old_mem, old_alignment, new_byte_count, len_align, return_address); | ||
| 226 | return old_mem.ptr[0..shrunk_len]; | ||
| 227 | } | ||
| 228 | if (self.rawResize(old_mem, old_alignment, new_byte_count, len_align, return_address)) |resized_len| { | ||
| 229 | assert(resized_len >= new_byte_count); | ||
| 230 | // TODO: https://github.com/ziglang/zig/issues/4298 | ||
| 231 | @memset(old_mem.ptr + new_byte_count, undefined, resized_len - new_byte_count); | ||
| 232 | return old_mem.ptr[0..resized_len]; | ||
| 233 | } else |_| {} | ||
| 234 | } | ||
| 235 | if (new_byte_count <= old_mem.len and new_alignment <= old_alignment) { | ||
| 236 | return error.OutOfMemory; | ||
| 237 | } | ||
| 238 | return self.moveBytes(old_mem, old_alignment, new_byte_count, new_alignment, len_align, return_address); | ||
| 239 | } | ||
| 240 | |||
| 241 | /// Move the given memory to a new location in the given allocator to accomodate a new | ||
| 242 | /// size and alignment. | ||
| 243 | fn moveBytes( | ||
| 244 | self: Allocator, | ||
| 245 | old_mem: []u8, | ||
| 246 | old_align: u29, | ||
| 247 | new_len: usize, | ||
| 248 | new_alignment: u29, | ||
| 249 | len_align: u29, | ||
| 250 | return_address: usize, | ||
| 251 | ) Error![]u8 { | ||
| 252 | assert(old_mem.len > 0); | ||
| 253 | assert(new_len > 0); | ||
| 254 | const new_mem = try self.rawAlloc(new_len, new_alignment, len_align, return_address); | ||
| 255 | @memcpy(new_mem.ptr, old_mem.ptr, math.min(new_len, old_mem.len)); | ||
| 256 | // TODO https://github.com/ziglang/zig/issues/4298 | ||
| 257 | @memset(old_mem.ptr, undefined, old_mem.len); | ||
| 258 | self.rawFree(old_mem, old_align, return_address); | ||
| 259 | return new_mem; | ||
| 260 | } | ||
| 261 | |||
| 262 | /// Returns a pointer to undefined memory. | 167 | /// Returns a pointer to undefined memory. |
| 263 | /// Call `destroy` with the result to free the memory. | 168 | /// Call `destroy` with the result to free the memory. |
| 264 | pub fn create(self: Allocator, comptime T: type) Error!*T { | 169 | pub fn create(self: Allocator, comptime T: type) Error!*T { |
| ... | @@ -409,7 +314,7 @@ pub fn allocAdvancedWithRetAddr( | ... | @@ -409,7 +314,7 @@ pub fn allocAdvancedWithRetAddr( |
| 409 | } | 314 | } |
| 410 | 315 | ||
| 411 | /// Increases or decreases the size of an allocation. It is guaranteed to not move the pointer. | 316 | /// Increases or decreases the size of an allocation. It is guaranteed to not move the pointer. |
| 412 | pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { | 317 | pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) ?@TypeOf(old_mem) { |
| 413 | const Slice = @typeInfo(@TypeOf(old_mem)).Pointer; | 318 | const Slice = @typeInfo(@TypeOf(old_mem)).Pointer; |
| 414 | const T = Slice.child; | 319 | const T = Slice.child; |
| 415 | if (new_n == 0) { | 320 | if (new_n == 0) { |
| ... | @@ -417,8 +322,8 @@ pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old | ... | @@ -417,8 +322,8 @@ pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old |
| 417 | return &[0]T{}; | 322 | return &[0]T{}; |
| 418 | } | 323 | } |
| 419 | const old_byte_slice = mem.sliceAsBytes(old_mem); | 324 | const old_byte_slice = mem.sliceAsBytes(old_mem); |
| 420 | const new_byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; | 325 | const new_byte_count = math.mul(usize, @sizeOf(T), new_n) catch return null; |
| 421 | const rc = try self.rawResize(old_byte_slice, Slice.alignment, new_byte_count, 0, @returnAddress()); | 326 | const rc = self.rawResize(old_byte_slice, Slice.alignment, new_byte_count, 0, @returnAddress()) orelse return null; |
| 422 | assert(rc == new_byte_count); | 327 | assert(rc == new_byte_count); |
| 423 | const new_byte_slice = old_byte_slice.ptr[0..new_byte_count]; | 328 | const new_byte_slice = old_byte_slice.ptr[0..new_byte_count]; |
| 424 | return mem.bytesAsSlice(T, new_byte_slice); | 329 | return mem.bytesAsSlice(T, new_byte_slice); |
| ... | @@ -488,8 +393,31 @@ pub fn reallocAdvancedWithRetAddr( | ... | @@ -488,8 +393,31 @@ pub fn reallocAdvancedWithRetAddr( |
| 488 | .exact => 0, | 393 | .exact => 0, |
| 489 | .at_least => @sizeOf(T), | 394 | .at_least => @sizeOf(T), |
| 490 | }; | 395 | }; |
| 491 | const new_byte_slice = try self.reallocBytes(old_byte_slice, Slice.alignment, byte_count, new_alignment, len_align, return_address); | 396 | |
| 492 | return mem.bytesAsSlice(T, @alignCast(new_alignment, new_byte_slice)); | 397 | if (mem.isAligned(@ptrToInt(old_byte_slice.ptr), new_alignment)) { |
| 398 | if (byte_count <= old_byte_slice.len) { | ||
| 399 | const shrunk_len = self.shrinkBytes(old_byte_slice, Slice.alignment, byte_count, len_align, return_address); | ||
| 400 | return mem.bytesAsSlice(T, @alignCast(new_alignment, old_byte_slice.ptr[0..shrunk_len])); | ||
| 401 | } | ||
| 402 | |||
| 403 | if (self.rawResize(old_byte_slice, Slice.alignment, byte_count, len_align, return_address)) |resized_len| { | ||
| 404 | // TODO: https://github.com/ziglang/zig/issues/4298 | ||
| 405 | @memset(old_byte_slice.ptr + byte_count, undefined, resized_len - byte_count); | ||
| 406 | return mem.bytesAsSlice(T, @alignCast(new_alignment, old_byte_slice.ptr[0..resized_len])); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | if (byte_count <= old_byte_slice.len and new_alignment <= Slice.alignment) { | ||
| 411 | return error.OutOfMemory; | ||
| 412 | } | ||
| 413 | |||
| 414 | const new_mem = try self.rawAlloc(byte_count, new_alignment, len_align, return_address); | ||
| 415 | @memcpy(new_mem.ptr, old_byte_slice.ptr, math.min(byte_count, old_byte_slice.len)); | ||
| 416 | // TODO https://github.com/ziglang/zig/issues/4298 | ||
| 417 | @memset(old_byte_slice.ptr, undefined, old_byte_slice.len); | ||
| 418 | self.rawFree(old_byte_slice, Slice.alignment, return_address); | ||
| 419 | |||
| 420 | return mem.bytesAsSlice(T, @alignCast(new_alignment, new_mem)); | ||
| 493 | } | 421 | } |
| 494 | 422 | ||
| 495 | /// Prefer calling realloc to shrink if you can tolerate failure, such as | 423 | /// Prefer calling realloc to shrink if you can tolerate failure, such as |
| ... | @@ -580,7 +508,7 @@ pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) ![:0]T { | ... | @@ -580,7 +508,7 @@ pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) ![:0]T { |
| 580 | } | 508 | } |
| 581 | 509 | ||
| 582 | /// Call `vtable.resize`, but caller guarantees that `new_len` <= `buf.len` meaning | 510 | /// Call `vtable.resize`, but caller guarantees that `new_len` <= `buf.len` meaning |
| 583 | /// error.OutOfMemory should be impossible. | 511 | /// than a `null` return value should be impossible. |
| 584 | /// This function allows a runtime `buf_align` value. Callers should generally prefer | 512 | /// This function allows a runtime `buf_align` value. Callers should generally prefer |
| 585 | /// to call `shrink` directly. | 513 | /// to call `shrink` directly. |
| 586 | pub fn shrinkBytes( | 514 | pub fn shrinkBytes( |
| ... | @@ -592,5 +520,5 @@ pub fn shrinkBytes( | ... | @@ -592,5 +520,5 @@ pub fn shrinkBytes( |
| 592 | return_address: usize, | 520 | return_address: usize, |
| 593 | ) usize { | 521 | ) usize { |
| 594 | assert(new_len <= buf.len); | 522 | assert(new_len <= buf.len); |
| 595 | return self.rawResize(buf, buf_align, new_len, len_align, return_address) catch unreachable; | 523 | return self.rawResize(buf, buf_align, new_len, len_align, return_address) orelse unreachable; |
| 596 | } | 524 | } |
lib/std/testing/failing_allocator.zig+2-5| ... | @@ -68,11 +68,8 @@ pub const FailingAllocator = struct { | ... | @@ -68,11 +68,8 @@ pub const FailingAllocator = struct { |
| 68 | new_len: usize, | 68 | new_len: usize, |
| 69 | len_align: u29, | 69 | len_align: u29, |
| 70 | ra: usize, | 70 | ra: usize, |
| 71 | ) error{OutOfMemory}!usize { | 71 | ) ?usize { |
| 72 | const r = self.internal_allocator.rawResize(old_mem, old_align, new_len, len_align, ra) catch |e| { | 72 | const r = self.internal_allocator.rawResize(old_mem, old_align, new_len, len_align, ra) orelse return null; |
| 73 | std.debug.assert(new_len > old_mem.len); | ||
| 74 | return e; | ||
| 75 | }; | ||
| 76 | if (r < old_mem.len) { | 73 | if (r < old_mem.len) { |
| 77 | self.freed_bytes += old_mem.len - r; | 74 | self.freed_bytes += old_mem.len - r; |
| 78 | } else { | 75 | } else { |
src/link/MachO.zig+1-1| ... | @@ -1288,7 +1288,7 @@ fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs: any | ... | @@ -1288,7 +1288,7 @@ fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs: any |
| 1288 | // TODO this should not be performed if the user specifies `-flat_namespace` flag. | 1288 | // TODO this should not be performed if the user specifies `-flat_namespace` flag. |
| 1289 | // See ld64 manpages. | 1289 | // See ld64 manpages. |
| 1290 | var arena_alloc = std.heap.ArenaAllocator.init(self.base.allocator); | 1290 | var arena_alloc = std.heap.ArenaAllocator.init(self.base.allocator); |
| 1291 | const arena = &arena_alloc.allocator; | 1291 | const arena = arena_alloc.allocator(); |
| 1292 | defer arena_alloc.deinit(); | 1292 | defer arena_alloc.deinit(); |
| 1293 | 1293 | ||
| 1294 | while (dependent_libs.readItem()) |*id| { | 1294 | while (dependent_libs.readItem()) |*id| { |
src/link/tapi.zig+1-1| ... | @@ -138,7 +138,7 @@ pub const LibStub = struct { | ... | @@ -138,7 +138,7 @@ pub const LibStub = struct { |
| 138 | err: { | 138 | err: { |
| 139 | log.debug("trying to parse as []TbdV3", .{}); | 139 | log.debug("trying to parse as []TbdV3", .{}); |
| 140 | const inner = lib_stub.yaml.parse([]TbdV3) catch break :err; | 140 | const inner = lib_stub.yaml.parse([]TbdV3) catch break :err; |
| 141 | var out = try lib_stub.yaml.arena.allocator.alloc(Tbd, inner.len); | 141 | var out = try lib_stub.yaml.arena.allocator().alloc(Tbd, inner.len); |
| 142 | for (inner) |doc, i| { | 142 | for (inner) |doc, i| { |
| 143 | out[i] = .{ .v3 = doc }; | 143 | out[i] = .{ .v3 = doc }; |
| 144 | } | 144 | } |
src/main.zig+1-1| ... | @@ -159,7 +159,7 @@ pub fn main() anyerror!void { | ... | @@ -159,7 +159,7 @@ pub fn main() anyerror!void { |
| 159 | 159 | ||
| 160 | if (tracy.enable_allocation) { | 160 | if (tracy.enable_allocation) { |
| 161 | var gpa_tracy = tracy.tracyAllocator(gpa); | 161 | var gpa_tracy = tracy.tracyAllocator(gpa); |
| 162 | return mainArgs(&gpa_tracy.allocator, arena, args); | 162 | return mainArgs(gpa_tracy.allocator(), arena, args); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | return mainArgs(gpa, arena, args); | 165 | return mainArgs(gpa, arena, args); |
src/tracy.zig+10-15| ... | @@ -113,20 +113,16 @@ pub fn TracyAllocator(comptime name: ?[:0]const u8) type { | ... | @@ -113,20 +113,16 @@ pub fn TracyAllocator(comptime name: ?[:0]const u8) type { |
| 113 | 113 | ||
| 114 | const Self = @This(); | 114 | const Self = @This(); |
| 115 | 115 | ||
| 116 | pub fn allocator(self: *Self) std.mem.Allocator { | 116 | pub fn init(parent_allocator: std.mem.Allocator) Self { |
| 117 | return std.mem.Allocator.init(self, allocFn, resizeFn); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn init(allocator: std.mem.Allocator) Self { | ||
| 121 | return .{ | 117 | return .{ |
| 122 | .parent_allocator = allocator, | 118 | .parent_allocator = parent_allocator, |
| 123 | .allocator = .{ | ||
| 124 | .allocFn = allocFn, | ||
| 125 | .resizeFn = resizeFn, | ||
| 126 | }, | ||
| 127 | }; | 119 | }; |
| 128 | } | 120 | } |
| 129 | 121 | ||
| 122 | pub fn allocator(self: *Self) std.mem.Allocator { | ||
| 123 | return std.mem.Allocator.init(self, allocFn, resizeFn, freeFn); | ||
| 124 | } | ||
| 125 | |||
| 130 | fn allocFn(self: *Self, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) std.mem.Allocator.Error![]u8 { | 126 | fn allocFn(self: *Self, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) std.mem.Allocator.Error![]u8 { |
| 131 | const result = self.parent_allocator.allocFn(self.parent_allocator, len, ptr_align, len_align, ret_addr); | 127 | const result = self.parent_allocator.allocFn(self.parent_allocator, len, ptr_align, len_align, ret_addr); |
| 132 | if (result) |data| { | 128 | if (result) |data| { |
| ... | @@ -162,12 +158,11 @@ pub fn TracyAllocator(comptime name: ?[:0]const u8) type { | ... | @@ -162,12 +158,11 @@ pub fn TracyAllocator(comptime name: ?[:0]const u8) type { |
| 162 | } | 158 | } |
| 163 | 159 | ||
| 164 | return resized_len; | 160 | return resized_len; |
| 165 | } else |err| { | ||
| 166 | // this is not really an error condition, during normal operation the compiler hits this case thousands of times | ||
| 167 | // due to this emitting messages for it is both slow and causes clutter | ||
| 168 | // messageColor("allocation resize failed", 0xFF0000); | ||
| 169 | return err; | ||
| 170 | } | 161 | } |
| 162 | |||
| 163 | // during normal operation the compiler hits this case thousands of times due to this | ||
| 164 | // emitting messages for it is both slow and causes clutter | ||
| 165 | return null; | ||
| 171 | } | 166 | } |
| 172 | 167 | ||
| 173 | fn freeFn(self: *Self, buf: []u8, buf_align: u29, ret_addr: usize) void { | 168 | fn freeFn(self: *Self, buf: []u8, buf_align: u29, ret_addr: usize) void { |
test/compare_output.zig+3-3| ... | @@ -496,7 +496,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -496,7 +496,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 496 | \\ var a = try allocator.alloc(u8, 10); | 496 | \\ var a = try allocator.alloc(u8, 10); |
| 497 | \\ a = allocator.shrink(a, 5); | 497 | \\ a = allocator.shrink(a, 5); |
| 498 | \\ try std.testing.expect(a.len == 5); | 498 | \\ try std.testing.expect(a.len == 5); |
| 499 | \\ try std.testing.expectError(error.OutOfMemory, allocator.resize(a, 20)); | 499 | \\ try std.testing.expect(allocator.resize(a, 20) == null); |
| 500 | \\ allocator.free(a); | 500 | \\ allocator.free(a); |
| 501 | \\} | 501 | \\} |
| 502 | \\ | 502 | \\ |
| ... | @@ -514,8 +514,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -514,8 +514,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 514 | , | 514 | , |
| 515 | \\debug: alloc - success - len: 10, ptr_align: 1, len_align: 0 | 515 | \\debug: alloc - success - len: 10, ptr_align: 1, len_align: 0 |
| 516 | \\debug: shrink - success - 10 to 5, len_align: 0, buf_align: 1 | 516 | \\debug: shrink - success - 10 to 5, len_align: 0, buf_align: 1 |
| 517 | \\error: expand - failure: OutOfMemory - 5 to 20, len_align: 0, buf_align: 1 | 517 | \\error: expand - failure - 5 to 20, len_align: 0, buf_align: 1 |
| 518 | \\debug: free - success - len: 5 | 518 | \\debug: free - len: 5 |
| 519 | \\ | 519 | \\ |
| 520 | ); | 520 | ); |
| 521 | } | 521 | } |
tools/update-linux-headers.zig+1-1| ... | @@ -131,7 +131,7 @@ const PathTable = std.StringHashMap(*TargetToHash); | ... | @@ -131,7 +131,7 @@ const PathTable = std.StringHashMap(*TargetToHash); |
| 131 | 131 | ||
| 132 | pub fn main() !void { | 132 | pub fn main() !void { |
| 133 | var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 133 | var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 134 | const arena = &arena_state.allocator; | 134 | const arena = arena_state.allocator(); |
| 135 | const args = try std.process.argsAlloc(arena); | 135 | const args = try std.process.argsAlloc(arena); |
| 136 | var search_paths = std.ArrayList([]const u8).init(arena); | 136 | var search_paths = std.ArrayList([]const u8).init(arena); |
| 137 | var opt_out_dir: ?[]const u8 = null; | 137 | var opt_out_dir: ?[]const u8 = null; |