| author | |
| committer | |
| log | 9b79ce1cd302a196bbb49e5fa89657bd840f4066 |
| tree | f717633b02bdd9cf1c7bc724908e8d19ef097981 |
| parent | 3063f0a5ed373947badd0af056db310283c76e37 |
| parent | 28dd9d478d24190ab5c8c4b892d7dfc16c380ae0 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
std/hash_map: fix ensureUnusedCapacity() over-allocating6 files changed, 36 insertions(+), 15 deletions(-)
lib/std/hash_map.zig+14-1| ... | @@ -848,7 +848,7 @@ pub fn HashMapUnmanaged( | ... | @@ -848,7 +848,7 @@ pub fn HashMapUnmanaged( |
| 848 | return ensureUnusedCapacityContext(self, allocator, additional_size, undefined); | 848 | return ensureUnusedCapacityContext(self, allocator, additional_size, undefined); |
| 849 | } | 849 | } |
| 850 | pub fn ensureUnusedCapacityContext(self: *Self, allocator: *Allocator, additional_size: Size, ctx: Context) !void { | 850 | pub fn ensureUnusedCapacityContext(self: *Self, allocator: *Allocator, additional_size: Size, ctx: Context) !void { |
| 851 | return ensureTotalCapacityContext(self, allocator, self.capacity() + additional_size, ctx); | 851 | return ensureTotalCapacityContext(self, allocator, self.count() + additional_size, ctx); |
| 852 | } | 852 | } |
| 853 | 853 | ||
| 854 | pub fn clearRetainingCapacity(self: *Self) void { | 854 | pub fn clearRetainingCapacity(self: *Self) void { |
| ... | @@ -1956,6 +1956,19 @@ test "std.hash_map getOrPutAdapted" { | ... | @@ -1956,6 +1956,19 @@ test "std.hash_map getOrPutAdapted" { |
| 1956 | } | 1956 | } |
| 1957 | } | 1957 | } |
| 1958 | 1958 | ||
| 1959 | test "std.hash_map ensureUnusedCapacity" { | ||
| 1960 | var map = AutoHashMap(u64, u64).init(testing.allocator); | ||
| 1961 | defer map.deinit(); | ||
| 1962 | |||
| 1963 | try map.ensureUnusedCapacity(32); | ||
| 1964 | const capacity = map.capacity(); | ||
| 1965 | try map.ensureUnusedCapacity(32); | ||
| 1966 | |||
| 1967 | // Repeated ensureUnusedCapacity() calls with no insertions between | ||
| 1968 | // should not change the capacity. | ||
| 1969 | try testing.expectEqual(capacity, map.capacity()); | ||
| 1970 | } | ||
| 1971 | |||
| 1959 | test "compile everything" { | 1972 | test "compile everything" { |
| 1960 | std.testing.refAllDecls(AutoHashMap(i32, i32)); | 1973 | std.testing.refAllDecls(AutoHashMap(i32, i32)); |
| 1961 | std.testing.refAllDecls(StringHashMap([]const u8)); | 1974 | std.testing.refAllDecls(StringHashMap([]const u8)); |
src/codegen/c.zig+3-3| ... | @@ -39,11 +39,11 @@ const BlockData = struct { | ... | @@ -39,11 +39,11 @@ const BlockData = struct { |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | pub const CValueMap = std.AutoHashMap(*Inst, CValue); | 41 | pub const CValueMap = std.AutoHashMap(*Inst, CValue); |
| 42 | pub const TypedefMap = std.HashMap( | 42 | pub const TypedefMap = std.ArrayHashMap( |
| 43 | Type, | 43 | Type, |
| 44 | struct { name: []const u8, rendered: []u8 }, | 44 | struct { name: []const u8, rendered: []u8 }, |
| 45 | Type.HashContext, | 45 | Type.HashContext32, |
| 46 | std.hash_map.default_max_load_percentage, | 46 | true, |
| 47 | ); | 47 | ); |
| 48 | 48 | ||
| 49 | fn formatTypeAsCIdentifier( | 49 | fn formatTypeAsCIdentifier( |
src/codegen/spirv.zig+1-1| ... | @@ -18,7 +18,7 @@ const Inst = ir.Inst; | ... | @@ -18,7 +18,7 @@ const Inst = ir.Inst; |
| 18 | pub const Word = u32; | 18 | pub const Word = u32; |
| 19 | pub const ResultId = u32; | 19 | pub const ResultId = u32; |
| 20 | 20 | ||
| 21 | pub const TypeMap = std.HashMap(Type, u32, Type.HashContext, std.hash_map.default_max_load_percentage); | 21 | pub const TypeMap = std.HashMap(Type, u32, Type.HashContext64, std.hash_map.default_max_load_percentage); |
| 22 | pub const InstMap = std.AutoHashMap(*Inst, ResultId); | 22 | pub const InstMap = std.AutoHashMap(*Inst, ResultId); |
| 23 | 23 | ||
| 24 | const IncomingBlock = struct { | 24 | const IncomingBlock = struct { |
src/link.zig+1-1| ... | @@ -168,7 +168,7 @@ pub const File = struct { | ... | @@ -168,7 +168,7 @@ pub const File = struct { |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | /// For DWARF .debug_info. | 170 | /// For DWARF .debug_info. |
| 171 | pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.HashContext, std.hash_map.default_max_load_percentage); | 171 | pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.HashContext64, std.hash_map.default_max_load_percentage); |
| 172 | 172 | ||
| 173 | /// For DWARF .debug_info. | 173 | /// For DWARF .debug_info. |
| 174 | pub const DbgInfoTypeReloc = struct { | 174 | pub const DbgInfoTypeReloc = struct { |
src/link/C.zig+5-8| ... | @@ -89,8 +89,7 @@ pub fn freeDecl(self: *C, decl: *Module.Decl) void { | ... | @@ -89,8 +89,7 @@ pub fn freeDecl(self: *C, decl: *Module.Decl) void { |
| 89 | fn deinitDecl(gpa: *Allocator, decl: *Module.Decl) void { | 89 | fn deinitDecl(gpa: *Allocator, decl: *Module.Decl) void { |
| 90 | decl.link.c.code.deinit(gpa); | 90 | decl.link.c.code.deinit(gpa); |
| 91 | decl.fn_link.c.fwd_decl.deinit(gpa); | 91 | decl.fn_link.c.fwd_decl.deinit(gpa); |
| 92 | var it = decl.fn_link.c.typedefs.valueIterator(); | 92 | for (decl.fn_link.c.typedefs.values()) |value| { |
| 93 | while (it.next()) |value| { | ||
| 94 | gpa.free(value.rendered); | 93 | gpa.free(value.rendered); |
| 95 | } | 94 | } |
| 96 | decl.fn_link.c.typedefs.deinit(gpa); | 95 | decl.fn_link.c.typedefs.deinit(gpa); |
| ... | @@ -108,8 +107,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | ... | @@ -108,8 +107,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 108 | const code = &decl.link.c.code; | 107 | const code = &decl.link.c.code; |
| 109 | fwd_decl.shrinkRetainingCapacity(0); | 108 | fwd_decl.shrinkRetainingCapacity(0); |
| 110 | { | 109 | { |
| 111 | var it = typedefs.valueIterator(); | 110 | for (typedefs.values()) |value| { |
| 112 | while (it.next()) |value| { | ||
| 113 | module.gpa.free(value.rendered); | 111 | module.gpa.free(value.rendered); |
| 114 | } | 112 | } |
| 115 | } | 113 | } |
| ... | @@ -135,8 +133,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | ... | @@ -135,8 +133,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 135 | object.blocks.deinit(module.gpa); | 133 | object.blocks.deinit(module.gpa); |
| 136 | object.code.deinit(); | 134 | object.code.deinit(); |
| 137 | object.dg.fwd_decl.deinit(); | 135 | object.dg.fwd_decl.deinit(); |
| 138 | var it = object.dg.typedefs.valueIterator(); | 136 | for (object.dg.typedefs.values()) |value| { |
| 139 | while (it.next()) |value| { | ||
| 140 | module.gpa.free(value.rendered); | 137 | module.gpa.free(value.rendered); |
| 141 | } | 138 | } |
| 142 | object.dg.typedefs.deinit(); | 139 | object.dg.typedefs.deinit(); |
| ... | @@ -207,7 +204,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { | ... | @@ -207,7 +204,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { |
| 207 | } | 204 | } |
| 208 | 205 | ||
| 209 | var fn_count: usize = 0; | 206 | var fn_count: usize = 0; |
| 210 | var typedefs = std.HashMap(Type, void, Type.HashContext, std.hash_map.default_max_load_percentage).init(comp.gpa); | 207 | var typedefs = std.HashMap(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage).init(comp.gpa); |
| 211 | defer typedefs.deinit(); | 208 | defer typedefs.deinit(); |
| 212 | 209 | ||
| 213 | // Typedefs, forward decls and non-functions first. | 210 | // Typedefs, forward decls and non-functions first. |
| ... | @@ -217,7 +214,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { | ... | @@ -217,7 +214,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { |
| 217 | if (!decl.has_tv) continue; | 214 | if (!decl.has_tv) continue; |
| 218 | const buf = buf: { | 215 | const buf = buf: { |
| 219 | if (decl.val.castTag(.function)) |_| { | 216 | if (decl.val.castTag(.function)) |_| { |
| 220 | try typedefs.ensureUnusedCapacity(decl.fn_link.c.typedefs.count()); | 217 | try typedefs.ensureUnusedCapacity(@intCast(u32, decl.fn_link.c.typedefs.count())); |
| 221 | var it = decl.fn_link.c.typedefs.iterator(); | 218 | var it = decl.fn_link.c.typedefs.iterator(); |
| 222 | while (it.next()) |new| { | 219 | while (it.next()) |new| { |
| 223 | const gop = typedefs.getOrPutAssumeCapacity(new.key_ptr.*); | 220 | const gop = typedefs.getOrPutAssumeCapacity(new.key_ptr.*); |
src/type.zig+12-1| ... | @@ -602,7 +602,7 @@ pub const Type = extern union { | ... | @@ -602,7 +602,7 @@ pub const Type = extern union { |
| 602 | return hasher.final(); | 602 | return hasher.final(); |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | pub const HashContext = struct { | 605 | pub const HashContext64 = struct { |
| 606 | pub fn hash(self: @This(), t: Type) u64 { | 606 | pub fn hash(self: @This(), t: Type) u64 { |
| 607 | _ = self; | 607 | _ = self; |
| 608 | return t.hash(); | 608 | return t.hash(); |
| ... | @@ -613,6 +613,17 @@ pub const Type = extern union { | ... | @@ -613,6 +613,17 @@ pub const Type = extern union { |
| 613 | } | 613 | } |
| 614 | }; | 614 | }; |
| 615 | 615 | ||
| 616 | pub const HashContext32 = struct { | ||
| 617 | pub fn hash(self: @This(), t: Type) u32 { | ||
| 618 | _ = self; | ||
| 619 | return @truncate(u32, t.hash()); | ||
| 620 | } | ||
| 621 | pub fn eql(self: @This(), a: Type, b: Type) bool { | ||
| 622 | _ = self; | ||
| 623 | return a.eql(b); | ||
| 624 | } | ||
| 625 | }; | ||
| 626 | |||
| 616 | pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type { | 627 | pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type { |
| 617 | if (self.tag_if_small_enough < Tag.no_payload_count) { | 628 | if (self.tag_if_small_enough < Tag.no_payload_count) { |
| 618 | return Type{ .tag_if_small_enough = self.tag_if_small_enough }; | 629 | return Type{ .tag_if_small_enough = self.tag_if_small_enough }; |