authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-05 01:04:44-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
logb14a350430aef737250b92520fa805201decf4d5
tree99838a0e2b949d9122c43bda71e05043e86dec63
parent00b723dc9dec6a85e2018c9875aeae32ea331ad7

std.heap.GeneralPurposeAllocator: reduce page size to 512K

and fix compilation on 32-bit targets

1 files changed, 7 insertions(+), 6 deletions(-)

lib/std/heap/general_purpose_allocator.zig+7-6
...@@ -104,12 +104,13 @@ const StackTrace = std.builtin.StackTrace;...@@ -104,12 +104,13 @@ const StackTrace = std.builtin.StackTrace;
104const page_size: usize = @max(std.heap.page_size_max, switch (builtin.os.tag) {104const page_size: usize = @max(std.heap.page_size_max, switch (builtin.os.tag) {
105 .windows => 64 * 1024, // Makes `std.heap.PageAllocator` take the happy path.105 .windows => 64 * 1024, // Makes `std.heap.PageAllocator` take the happy path.
106 .wasi => 64 * 1024, // Max alignment supported by `std.heap.WasmAllocator`.106 .wasi => 64 * 1024, // Max alignment supported by `std.heap.WasmAllocator`.
107 else => 2 * 1024 * 1024, // Avoids too many active mappings when `page_size_max` is low.107 else => 512 * 1024, // Avoids too many active mappings when `page_size_max` is low.
108});108});
109const page_align: mem.Alignment = .fromByteUnits(page_size);109const page_align: mem.Alignment = .fromByteUnits(page_size);
110110
111/// Integer type for pointing to slots in a small allocation111/// Integer type for pointing to slots in a small allocation
112const SlotIndex = std.meta.Int(.unsigned, math.log2(page_size) + 1);112const SlotIndex = std.meta.Int(.unsigned, math.log2(page_size) + 1);
113const Log2USize = std.math.Log2Int(usize);
113114
114const default_test_stack_trace_frames: usize = if (builtin.is_test) 10 else 6;115const default_test_stack_trace_frames: usize = if (builtin.is_test) 10 else 6;
115const default_sys_stack_trace_frames: usize = if (std.debug.sys_can_stack_trace) default_test_stack_trace_frames else 0;116const default_sys_stack_trace_frames: usize = if (std.debug.sys_can_stack_trace) default_test_stack_trace_frames else 0;
...@@ -383,7 +384,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -383,7 +384,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
383384
384 /// This is executed only at compile-time to prepopulate a lookup table.385 /// This is executed only at compile-time to prepopulate a lookup table.
385 fn calculateSlotCount(size_class_index: usize) SlotIndex {386 fn calculateSlotCount(size_class_index: usize) SlotIndex {
386 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));387 const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
387 var lower: usize = 8;388 var lower: usize = 8;
388 var upper: usize = (page_size - bucketSize(lower)) / size_class;389 var upper: usize = (page_size - bucketSize(lower)) / size_class;
389 while (upper > lower) {390 while (upper > lower) {
...@@ -408,7 +409,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -408,7 +409,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
408 }409 }
409410
410 fn detectLeaksInBucket(bucket: *BucketHeader, size_class_index: usize, used_bits_count: usize) bool {411 fn detectLeaksInBucket(bucket: *BucketHeader, size_class_index: usize, used_bits_count: usize) bool {
411 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));412 const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
412 const slot_count = slot_counts[size_class_index];413 const slot_count = slot_counts[size_class_index];
413 var leaks = false;414 var leaks = false;
414 var used_bits_byte: usize = 0;415 var used_bits_byte: usize = 0;
...@@ -745,7 +746,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -745,7 +746,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
745 const used_bits_byte = bucket.usedBits(slot_index / 8);746 const used_bits_byte = bucket.usedBits(slot_index / 8);
746 const used_bit_index: u3 = @intCast(slot_index % 8);747 const used_bit_index: u3 = @intCast(slot_index % 8);
747 used_bits_byte.* |= (@as(u8, 1) << used_bit_index);748 used_bits_byte.* |= (@as(u8, 1) << used_bit_index);
748 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));749 const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
749 if (config.stack_trace_frames > 0) {750 if (config.stack_trace_frames > 0) {
750 bucket.captureStackTrace(ret_addr, slot_count, slot_index, .alloc);751 bucket.captureStackTrace(ret_addr, slot_count, slot_index, .alloc);
751 }752 }
...@@ -858,7 +859,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -858,7 +859,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
858 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);859 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);
859 if (bucket.canary != config.canary) @panic("Invalid free");860 if (bucket.canary != config.canary) @panic("Invalid free");
860 const page_offset = freed_addr - page_addr;861 const page_offset = freed_addr - page_addr;
861 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));862 const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
862 const slot_index: SlotIndex = @intCast(page_offset / size_class);863 const slot_index: SlotIndex = @intCast(page_offset / size_class);
863 const used_byte_index = slot_index / 8;864 const used_byte_index = slot_index / 8;
864 const used_bit_index: u3 = @intCast(slot_index % 8);865 const used_bit_index: u3 = @intCast(slot_index % 8);
...@@ -953,7 +954,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -953,7 +954,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
953 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);954 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);
954 if (bucket.canary != config.canary) @panic("Invalid free");955 if (bucket.canary != config.canary) @panic("Invalid free");
955 const page_offset = memory_addr - page_addr;956 const page_offset = memory_addr - page_addr;
956 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));957 const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
957 const slot_index: SlotIndex = @intCast(page_offset / size_class);958 const slot_index: SlotIndex = @intCast(page_offset / size_class);
958 const used_byte_index = slot_index / 8;959 const used_byte_index = slot_index / 8;
959 const used_bit_index: u3 = @intCast(slot_index % 8);960 const used_bit_index: u3 = @intCast(slot_index % 8);