| ... | @@ -319,11 +319,18 @@ pub fn rehashTrackedInsts( | ... | @@ -319,11 +319,18 @@ pub fn rehashTrackedInsts( |
| 319 | // We know how big each shard must be, so ensure we have the capacity we need. | 319 | // We know how big each shard must be, so ensure we have the capacity we need. |
| 320 | for (ip.shards) |*shard| { | 320 | for (ip.shards) |*shard| { |
| 321 | const want_capacity = if (shard.mutate.tracked_inst_map.len == 0) 0 else cap: { | 321 | const want_capacity = if (shard.mutate.tracked_inst_map.len == 0) 0 else cap: { |
| 322 | break :cap std.math.ceilPowerOfTwo(u32, shard.mutate.tracked_inst_map.len * 5 / 3) catch unreachable; | 322 | // We need to return a capacity of at least 2 to make sure we don't have the `Map(...).empty` value. |
| | 323 | // For this reason, note the `+ 1` in the below expression. This matches the behavior of `trackZir`. |
| | 324 | break :cap std.math.ceilPowerOfTwo(u32, shard.mutate.tracked_inst_map.len * 5 / 3 + 1) catch unreachable; |
| 323 | }; | 325 | }; |
| 324 | const have_capacity = shard.shared.tracked_inst_map.header().capacity; // no acquire because we hold the mutex | 326 | const have_capacity = shard.shared.tracked_inst_map.header().capacity; // no acquire because we hold the mutex |
| 325 | if (have_capacity >= want_capacity) { | 327 | if (have_capacity >= want_capacity) { |
| 326 | @memset(shard.shared.tracked_inst_map.entries[0..have_capacity], .{ .value = .none, .hash = undefined }); | 328 | if (have_capacity == 1) { |
| | 329 | // The map is `.empty` -- we can't memset the entries, or we'll segfault, because |
| | 330 | // the buffer is secretly constant. |
| | 331 | } else { |
| | 332 | @memset(shard.shared.tracked_inst_map.entries[0..have_capacity], .{ .value = .none, .hash = undefined }); |
| | 333 | } |
| 327 | continue; | 334 | continue; |
| 328 | } | 335 | } |
| 329 | var arena = arena_state.promote(gpa); | 336 | var arena = arena_state.promote(gpa); |