| author | |
| committer | |
| log | 594cb38fcb6c2edccee6b2fd74adec81b3be547a |
| tree | c8a29f062fac286cfef622737affaaadc4ff4d73 |
| parent | 010d9a63f20d8a4bd14cff0ada690b2d127a0371 |
| parent | 3cc0fc601af62adebf6b9f3bb1a241fa8a501d0b |
| signature |
std: remove loop from growCapacity6 files changed, 18 insertions(+), 67 deletions(-)
lib/std/Io/Writer.zig+1-1| ... | ... | @@ -2667,7 +2667,7 @@ pub const Allocating = struct { |
| 2667 | 2667 | pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void { |
| 2668 | 2668 | // Protects growing unnecessarily since better_capacity will be larger. |
| 2669 | 2669 | if (a.writer.buffer.len >= new_capacity) return; |
| 2670 | const better_capacity = ArrayList(u8).growCapacity(a.writer.buffer.len, new_capacity); | |
| 2670 | const better_capacity = ArrayList(u8).growCapacity(new_capacity); | |
| 2671 | 2671 | return ensureTotalCapacityPrecise(a, better_capacity); |
| 2672 | 2672 | } |
| 2673 | 2673 |
lib/std/array_list.zig+6-11| ... | ... | @@ -172,7 +172,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 172 | 172 | // a new buffer and doing our own copy. With a realloc() call, |
| 173 | 173 | // the allocator implementation would pointlessly copy our |
| 174 | 174 | // extra capacity. |
| 175 | const new_capacity = Aligned(T, alignment).growCapacity(self.capacity, new_len); | |
| 175 | const new_capacity = Aligned(T, alignment).growCapacity(new_len); | |
| 176 | 176 | const old_memory = self.allocatedSlice(); |
| 177 | 177 | if (self.allocator.remap(old_memory, new_capacity)) |new_memory| { |
| 178 | 178 | self.items.ptr = new_memory.ptr; |
| ... | ... | @@ -408,7 +408,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 408 | 408 | // Protects growing unnecessarily since better_capacity will be larger. |
| 409 | 409 | if (self.capacity >= new_capacity) return; |
| 410 | 410 | |
| 411 | const better_capacity = Aligned(T, alignment).growCapacity(self.capacity, new_capacity); | |
| 411 | const better_capacity = Aligned(T, alignment).growCapacity(new_capacity); | |
| 412 | 412 | return self.ensureTotalCapacityPrecise(better_capacity); |
| 413 | 413 | } |
| 414 | 414 | |
| ... | ... | @@ -1160,7 +1160,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1160 | 1160 | /// Invalidates element pointers if additional memory is needed. |
| 1161 | 1161 | pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1162 | 1162 | if (self.capacity >= new_capacity) return; |
| 1163 | return self.ensureTotalCapacityPrecise(gpa, growCapacity(self.capacity, new_capacity)); | |
| 1163 | return self.ensureTotalCapacityPrecise(gpa, growCapacity(new_capacity)); | |
| 1164 | 1164 | } |
| 1165 | 1165 | |
| 1166 | 1166 | /// If the current capacity is less than `new_capacity`, this function will |
| ... | ... | @@ -1359,17 +1359,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1359 | 1359 | return self.getLast(); |
| 1360 | 1360 | } |
| 1361 | 1361 | |
| 1362 | const init_capacity = @as(comptime_int, @max(1, std.atomic.cache_line / @sizeOf(T))); | |
| 1362 | const init_capacity: comptime_int = @max(1, std.atomic.cache_line / @sizeOf(T)); | |
| 1363 | 1363 | |
| 1364 | 1364 | /// Called when memory growth is necessary. Returns a capacity larger than |
| 1365 | 1365 | /// minimum that grows super-linearly. |
| 1366 | pub fn growCapacity(current: usize, minimum: usize) usize { | |
| 1367 | var new = current; | |
| 1368 | while (true) { | |
| 1369 | new +|= new / 2 + init_capacity; | |
| 1370 | if (new >= minimum) | |
| 1371 | return new; | |
| 1372 | } | |
| 1366 | pub fn growCapacity(minimum: usize) usize { | |
| 1367 | return minimum +| (minimum / 2 + init_capacity); | |
| 1373 | 1368 | } |
| 1374 | 1369 | }; |
| 1375 | 1370 | } |
lib/std/deque.zig+1-13| ... | ... | @@ -56,7 +56,7 @@ pub fn Deque(comptime T: type) type { |
| 56 | 56 | /// Invalidates element pointers if additional memory is needed. |
| 57 | 57 | pub fn ensureTotalCapacity(deque: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| 58 | 58 | if (deque.buffer.len >= new_capacity) return; |
| 59 | return deque.ensureTotalCapacityPrecise(gpa, growCapacity(deque.buffer.len, new_capacity)); | |
| 59 | return deque.ensureTotalCapacityPrecise(gpa, std.ArrayList(T).growCapacity(new_capacity)); | |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | /// If the current capacity is less than `new_capacity`, this function will |
| ... | ... | @@ -243,18 +243,6 @@ pub fn Deque(comptime T: type) type { |
| 243 | 243 | return index - head_len; |
| 244 | 244 | } |
| 245 | 245 | } |
| 246 | ||
| 247 | const init_capacity: comptime_int = @max(1, std.atomic.cache_line / @sizeOf(T)); | |
| 248 | ||
| 249 | /// Called when memory growth is necessary. Returns a capacity larger than | |
| 250 | /// minimum that grows super-linearly. | |
| 251 | fn growCapacity(current: usize, minimum: usize) usize { | |
| 252 | var new = current; | |
| 253 | while (true) { | |
| 254 | new +|= new / 2 + init_capacity; | |
| 255 | if (new >= minimum) return new; | |
| 256 | } | |
| 257 | } | |
| 258 | 246 | }; |
| 259 | 247 | } |
| 260 | 248 |
lib/std/json/scanner_test.zig-27| ... | ... | @@ -431,33 +431,6 @@ test "skipValue" { |
| 431 | 431 | try std.testing.expectError(error.SyntaxError, testSkipValue("[102, 111, 111}")); |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | fn testEnsureStackCapacity(do_ensure: bool) !void { | |
| 435 | var fail_alloc = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 1 }); | |
| 436 | const failing_allocator = fail_alloc.allocator(); | |
| 437 | ||
| 438 | const nestings = 2049; // intentionally not a power of 2. | |
| 439 | var input_string: std.ArrayListUnmanaged(u8) = .empty; | |
| 440 | try input_string.appendNTimes(std.testing.allocator, '[', nestings); | |
| 441 | try input_string.appendNTimes(std.testing.allocator, ']', nestings); | |
| 442 | defer input_string.deinit(std.testing.allocator); | |
| 443 | ||
| 444 | var scanner = Scanner.initCompleteInput(failing_allocator, input_string.items); | |
| 445 | defer scanner.deinit(); | |
| 446 | ||
| 447 | if (do_ensure) { | |
| 448 | try scanner.ensureTotalStackCapacity(nestings); | |
| 449 | } | |
| 450 | ||
| 451 | try scanner.skipValue(); | |
| 452 | try std.testing.expectEqual(Token.end_of_document, try scanner.next()); | |
| 453 | } | |
| 454 | test "ensureTotalStackCapacity" { | |
| 455 | // Once to demonstrate failure. | |
| 456 | try std.testing.expectError(error.OutOfMemory, testEnsureStackCapacity(false)); | |
| 457 | // Then to demonstrate it works. | |
| 458 | try testEnsureStackCapacity(true); | |
| 459 | } | |
| 460 | ||
| 461 | 434 | fn testDiagnosticsFromSource(expected_error: ?anyerror, line: u64, col: u64, byte_offset: u64, source: anytype) !void { |
| 462 | 435 | var diagnostics = Diagnostics{}; |
| 463 | 436 | source.enableDiagnostics(&diagnostics); |
lib/std/json/static_test.zig+1-1| ... | ... | @@ -914,7 +914,7 @@ test "parse at comptime" { |
| 914 | 914 | uptime: u64, |
| 915 | 915 | }; |
| 916 | 916 | const config = comptime x: { |
| 917 | var buf: [256]u8 = undefined; | |
| 917 | var buf: [300]u8 = undefined; | |
| 918 | 918 | var fba = std.heap.FixedBufferAllocator.init(&buf); |
| 919 | 919 | const res = parseFromSliceLeaky(Config, fba.allocator(), doc, .{}); |
| 920 | 920 | // Assert no error can occur since we are |
lib/std/multi_array_list.zig+9-14| ... | ... | @@ -457,24 +457,19 @@ pub fn MultiArrayList(comptime T: type) type { |
| 457 | 457 | /// Invalidates element pointers if additional memory is needed. |
| 458 | 458 | pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| 459 | 459 | if (self.capacity >= new_capacity) return; |
| 460 | return self.setCapacity(gpa, growCapacity(self.capacity, new_capacity)); | |
| 460 | return self.setCapacity(gpa, growCapacity(new_capacity)); | |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | const init_capacity = init: { | |
| 464 | var max = 1; | |
| 465 | for (fields) |field| max = @as(comptime_int, @max(max, @sizeOf(field.type))); | |
| 466 | break :init @as(comptime_int, @max(1, std.atomic.cache_line / max)); | |
| 463 | const init_capacity: comptime_int = init: { | |
| 464 | var max: comptime_int = 1; | |
| 465 | for (fields) |field| max = @max(max, @sizeOf(field.type)); | |
| 466 | break :init @max(1, std.atomic.cache_line / max); | |
| 467 | 467 | }; |
| 468 | 468 | |
| 469 | /// Called when memory growth is necessary. Returns a capacity larger than | |
| 470 | /// minimum that grows super-linearly. | |
| 471 | fn growCapacity(current: usize, minimum: usize) usize { | |
| 472 | var new = current; | |
| 473 | while (true) { | |
| 474 | new +|= new / 2 + init_capacity; | |
| 475 | if (new >= minimum) | |
| 476 | return new; | |
| 477 | } | |
| 469 | /// Given a lower bound of required memory capacity, returns a larger value | |
| 470 | /// with super-linear growth. | |
| 471 | pub fn growCapacity(minimum: usize) usize { | |
| 472 | return minimum +| (minimum / 2 + init_capacity); | |
| 478 | 473 | } |
| 479 | 474 | |
| 480 | 475 | /// Modify the array so that it can hold at least `additional_count` **more** items. |