authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 15:37:04-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 19:02:55-04:00
log2c89f3b65427e8ca733a9977ded4e8c6f0a89650
tree31649a654f955efd0dc8b5e8c25622fb3f257c45
parentafa66fa392f5a32d16da7f4705c59dad369f6d48

InternPool: make `maps` thread-safe


1 files changed, 115 insertions(+), 55 deletions(-)

src/InternPool.zig+115-55
...@@ -13,13 +13,6 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_th...@@ -13,13 +13,6 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_th
13/// Cached shift amount to put a `tid` in the top bits of a 32-bit value.13/// Cached shift amount to put a `tid` in the top bits of a 32-bit value.
14tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31,14tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31,
1515
16/// Some types such as enums, structs, and unions need to store mappings from field names
17/// to field index, or value to field index. In such cases, they will store the underlying
18/// field names and values directly, relying on one of these maps, stored separately,
19/// to provide lookup.
20/// These are not serialized; it is computed upon deserialization.
21maps: std.ArrayListUnmanaged(FieldMap) = .{},
22
23/// Dependencies on the source code hash associated with a ZIR instruction.16/// Dependencies on the source code hash associated with a ZIR instruction.
24/// * For a `declaration`, this is the entire declaration body.17/// * For a `declaration`, this is the entire declaration body.
25/// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations).18/// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations).
...@@ -428,6 +421,7 @@ const Local = struct {...@@ -428,6 +421,7 @@ const Local = struct {
428 strings: ListMutate,421 strings: ListMutate,
429 tracked_insts: MutexListMutate,422 tracked_insts: MutexListMutate,
430 files: ListMutate,423 files: ListMutate,
424 maps: ListMutate,
431425
432 decls: BucketListMutate,426 decls: BucketListMutate,
433 namespaces: BucketListMutate,427 namespaces: BucketListMutate,
...@@ -440,6 +434,7 @@ const Local = struct {...@@ -440,6 +434,7 @@ const Local = struct {
440 strings: Strings,434 strings: Strings,
441 tracked_insts: TrackedInsts,435 tracked_insts: TrackedInsts,
442 files: List(File),436 files: List(File),
437 maps: Maps,
443438
444 decls: Decls,439 decls: Decls,
445 namespaces: Namespaces,440 namespaces: Namespaces,
...@@ -461,6 +456,7 @@ const Local = struct {...@@ -461,6 +456,7 @@ const Local = struct {
461 };456 };
462 const Strings = List(struct { u8 });457 const Strings = List(struct { u8 });
463 const TrackedInsts = List(struct { TrackedInst });458 const TrackedInsts = List(struct { TrackedInst });
459 const Maps = List(struct { FieldMap });
464460
465 const decls_bucket_width = 8;461 const decls_bucket_width = 8;
466 const decls_bucket_mask = (1 << decls_bucket_width) - 1;462 const decls_bucket_mask = (1 << decls_bucket_width) - 1;
...@@ -536,14 +532,17 @@ const Local = struct {...@@ -536,14 +532,17 @@ const Local = struct {
536 .is_tuple = elem_info.is_tuple,532 .is_tuple = elem_info.is_tuple,
537 } });533 } });
538 }534 }
539 fn SliceElem(comptime opts: struct { is_const: bool = false }) type {535 fn PtrElem(comptime opts: struct {
536 size: std.builtin.Type.Pointer.Size,
537 is_const: bool = false,
538 }) type {
540 const elem_info = @typeInfo(Elem).Struct;539 const elem_info = @typeInfo(Elem).Struct;
541 const elem_fields = elem_info.fields;540 const elem_fields = elem_info.fields;
542 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;541 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;
543 for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{542 for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{
544 .name = elem_field.name,543 .name = elem_field.name,
545 .type = @Type(.{ .Pointer = .{544 .type = @Type(.{ .Pointer = .{
546 .size = .Slice,545 .size = opts.size,
547 .is_const = opts.is_const,546 .is_const = opts.is_const,
548 .is_volatile = false,547 .is_volatile = false,
549 .alignment = 0,548 .alignment = 0,
...@@ -564,6 +563,23 @@ const Local = struct {...@@ -564,6 +563,23 @@ const Local = struct {
564 } });563 } });
565 }564 }
566565
566 pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .One }) {
567 try mutable.ensureUnusedCapacity(1);
568 return mutable.addOneAssumeCapacity();
569 }
570
571 pub fn addOneAssumeCapacity(mutable: Mutable) PtrElem(.{ .size = .One }) {
572 const index = mutable.mutate.len;
573 assert(index < mutable.list.header().capacity);
574 mutable.mutate.len = index + 1;
575 const mutable_view = mutable.view().slice();
576 var ptr: PtrElem(.{ .size = .One }) = undefined;
577 inline for (fields) |field| {
578 @field(ptr, @tagName(field)) = &mutable_view.items(field)[index];
579 }
580 return ptr;
581 }
582
567 pub fn append(mutable: Mutable, elem: Elem) Allocator.Error!void {583 pub fn append(mutable: Mutable, elem: Elem) Allocator.Error!void {
568 try mutable.ensureUnusedCapacity(1);584 try mutable.ensureUnusedCapacity(1);
569 mutable.appendAssumeCapacity(elem);585 mutable.appendAssumeCapacity(elem);
...@@ -577,14 +593,14 @@ const Local = struct {...@@ -577,14 +593,14 @@ const Local = struct {
577593
578 pub fn appendSliceAssumeCapacity(594 pub fn appendSliceAssumeCapacity(
579 mutable: Mutable,595 mutable: Mutable,
580 slice: SliceElem(.{ .is_const = true }),596 slice: PtrElem(.{ .size = .Slice, .is_const = true }),
581 ) void {597 ) void {
582 if (fields.len == 0) return;598 if (fields.len == 0) return;
583 const start = mutable.mutate.len;599 const start = mutable.mutate.len;
584 const slice_len = @field(slice, @tagName(fields[0])).len;600 const slice_len = @field(slice, @tagName(fields[0])).len;
585 assert(slice_len <= mutable.list.header().capacity - start);601 assert(slice_len <= mutable.list.header().capacity - start);
586 mutable.mutate.len = @intCast(start + slice_len);602 mutable.mutate.len = @intCast(start + slice_len);
587 const mutable_view = mutable.view();603 const mutable_view = mutable.view().slice();
588 inline for (fields) |field| {604 inline for (fields) |field| {
589 const field_slice = @field(slice, @tagName(field));605 const field_slice = @field(slice, @tagName(field));
590 assert(field_slice.len == slice_len);606 assert(field_slice.len == slice_len);
...@@ -601,7 +617,7 @@ const Local = struct {...@@ -601,7 +617,7 @@ const Local = struct {
601 const start = mutable.mutate.len;617 const start = mutable.mutate.len;
602 assert(len <= mutable.list.header().capacity - start);618 assert(len <= mutable.list.header().capacity - start);
603 mutable.mutate.len = @intCast(start + len);619 mutable.mutate.len = @intCast(start + len);
604 const mutable_view = mutable.view();620 const mutable_view = mutable.view().slice();
605 inline for (fields) |field| {621 inline for (fields) |field| {
606 @memset(mutable_view.items(field)[start..][0..len], @field(elem, @tagName(field)));622 @memset(mutable_view.items(field)[start..][0..len], @field(elem, @tagName(field)));
607 }623 }
...@@ -616,7 +632,7 @@ const Local = struct {...@@ -616,7 +632,7 @@ const Local = struct {
616 const start = mutable.mutate.len;632 const start = mutable.mutate.len;
617 assert(len <= mutable.list.header().capacity - start);633 assert(len <= mutable.list.header().capacity - start);
618 mutable.mutate.len = @intCast(start + len);634 mutable.mutate.len = @intCast(start + len);
619 const mutable_view = mutable.view();635 const mutable_view = mutable.view().slice();
620 var ptr_array: PtrArrayElem(len) = undefined;636 var ptr_array: PtrArrayElem(len) = undefined;
621 inline for (fields) |field| {637 inline for (fields) |field| {
622 @field(ptr_array, @tagName(field)) = mutable_view.items(field)[start..][0..len];638 @field(ptr_array, @tagName(field)) = mutable_view.items(field)[start..][0..len];
...@@ -624,17 +640,17 @@ const Local = struct {...@@ -624,17 +640,17 @@ const Local = struct {
624 return ptr_array;640 return ptr_array;
625 }641 }
626642
627 pub fn addManyAsSlice(mutable: Mutable, len: usize) Allocator.Error!SliceElem(.{}) {643 pub fn addManyAsSlice(mutable: Mutable, len: usize) Allocator.Error!PtrElem(.{ .size = .Slice }) {
628 try mutable.ensureUnusedCapacity(len);644 try mutable.ensureUnusedCapacity(len);
629 return mutable.addManyAsSliceAssumeCapacity(len);645 return mutable.addManyAsSliceAssumeCapacity(len);
630 }646 }
631647
632 pub fn addManyAsSliceAssumeCapacity(mutable: Mutable, len: usize) SliceElem(.{}) {648 pub fn addManyAsSliceAssumeCapacity(mutable: Mutable, len: usize) PtrElem(.{ .size = .Slice }) {
633 const start = mutable.mutate.len;649 const start = mutable.mutate.len;
634 assert(len <= mutable.list.header().capacity - start);650 assert(len <= mutable.list.header().capacity - start);
635 mutable.mutate.len = @intCast(start + len);651 mutable.mutate.len = @intCast(start + len);
636 const mutable_view = mutable.view();652 const mutable_view = mutable.view().slice();
637 var slice: SliceElem(.{}) = undefined;653 var slice: PtrElem(.{ .size = .Slice }) = undefined;
638 inline for (fields) |field| {654 inline for (fields) |field| {
639 @field(slice, @tagName(field)) = mutable_view.items(field)[start..][0..len];655 @field(slice, @tagName(field)) = mutable_view.items(field)[start..][0..len];
640 }656 }
...@@ -807,6 +823,20 @@ const Local = struct {...@@ -807,6 +823,20 @@ const Local = struct {
807 };823 };
808 }824 }
809825
826 /// Some types such as enums, structs, and unions need to store mappings from field names
827 /// to field index, or value to field index. In such cases, they will store the underlying
828 /// field names and values directly, relying on one of these maps, stored separately,
829 /// to provide lookup.
830 /// These are not serialized; it is computed upon deserialization.
831 pub fn getMutableMaps(local: *Local, gpa: Allocator) Maps.Mutable {
832 return .{
833 .gpa = gpa,
834 .arena = &local.mutate.arena,
835 .mutate = &local.mutate.maps,
836 .list = &local.shared.maps,
837 };
838 }
839
810 /// Rather than allocating Decl objects with an Allocator, we instead allocate840 /// Rather than allocating Decl objects with an Allocator, we instead allocate
811 /// them with this BucketList. This provides four advantages:841 /// them with this BucketList. This provides four advantages:
812 /// * Stable memory so that one thread can access a Decl object while another842 /// * Stable memory so that one thread can access a Decl object while another
...@@ -961,9 +991,37 @@ pub const OptionalMapIndex = enum(u32) {...@@ -961,9 +991,37 @@ pub const OptionalMapIndex = enum(u32) {
961pub const MapIndex = enum(u32) {991pub const MapIndex = enum(u32) {
962 _,992 _,
963993
994 pub fn get(map_index: MapIndex, ip: *InternPool) *FieldMap {
995 const unwrapped_map_index = map_index.unwrap(ip);
996 const maps = ip.getLocalShared(unwrapped_map_index.tid).maps.acquire();
997 return &maps.view().items(.@"0")[unwrapped_map_index.index];
998 }
999
1000 pub fn getConst(map_index: MapIndex, ip: *const InternPool) FieldMap {
1001 return map_index.get(@constCast(ip)).*;
1002 }
1003
964 pub fn toOptional(i: MapIndex) OptionalMapIndex {1004 pub fn toOptional(i: MapIndex) OptionalMapIndex {
965 return @enumFromInt(@intFromEnum(i));1005 return @enumFromInt(@intFromEnum(i));
966 }1006 }
1007
1008 const Unwrapped = struct {
1009 tid: Zcu.PerThread.Id,
1010 index: u32,
1011
1012 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) MapIndex {
1013 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
1014 assert(unwrapped.index <= ip.getIndexMask(u32));
1015 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 |
1016 unwrapped.index);
1017 }
1018 };
1019 fn unwrap(map_index: MapIndex, ip: *const InternPool) Unwrapped {
1020 return .{
1021 .tid = @enumFromInt(@intFromEnum(map_index) >> ip.tid_shift_32 & ip.getTidMask()),
1022 .index = @intFromEnum(map_index) & ip.getIndexMask(u32),
1023 };
1024 }
967};1025};
9681026
969pub const RuntimeIndex = enum(u32) {1027pub const RuntimeIndex = enum(u32) {
...@@ -1398,7 +1456,7 @@ pub const Key = union(enum) {...@@ -1398,7 +1456,7 @@ pub const Key = union(enum) {
13981456
1399 /// Look up field index based on field name.1457 /// Look up field index based on field name.
1400 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {1458 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
1401 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];1459 const map = self.names_map.unwrap().?.getConst(ip);
1402 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };1460 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
1403 const field_index = map.getIndexAdapted(name, adapter) orelse return null;1461 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
1404 return @intCast(field_index);1462 return @intCast(field_index);
...@@ -2823,7 +2881,7 @@ pub const LoadedStructType = struct {...@@ -2823,7 +2881,7 @@ pub const LoadedStructType = struct {
2823 if (i >= self.field_types.len) return null;2881 if (i >= self.field_types.len) return null;
2824 return i;2882 return i;
2825 };2883 };
2826 const map = &ip.maps.items[@intFromEnum(names_map)];2884 const map = names_map.getConst(ip);
2827 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };2885 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };
2828 const field_index = map.getIndexAdapted(name, adapter) orelse return null;2886 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
2829 return @intCast(field_index);2887 return @intCast(field_index);
...@@ -3350,7 +3408,7 @@ const LoadedEnumType = struct {...@@ -3350,7 +3408,7 @@ const LoadedEnumType = struct {
33503408
3351 /// Look up field index based on field name.3409 /// Look up field index based on field name.
3352 pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {3410 pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
3353 const map = &ip.maps.items[@intFromEnum(self.names_map)];3411 const map = self.names_map.getConst(ip);
3354 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };3412 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
3355 const field_index = map.getIndexAdapted(name, adapter) orelse return null;3413 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
3356 return @intCast(field_index);3414 return @intCast(field_index);
...@@ -3370,7 +3428,7 @@ const LoadedEnumType = struct {...@@ -3370,7 +3428,7 @@ const LoadedEnumType = struct {
3370 else => unreachable,3428 else => unreachable,
3371 };3429 };
3372 if (self.values_map.unwrap()) |values_map| {3430 if (self.values_map.unwrap()) |values_map| {
3373 const map = &ip.maps.items[@intFromEnum(values_map)];3431 const map = values_map.getConst(ip);
3374 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };3432 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
3375 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;3433 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
3376 return @intCast(field_index);3434 return @intCast(field_index);
...@@ -5370,6 +5428,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -5370,6 +5428,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
5370 .strings = Local.Strings.empty,5428 .strings = Local.Strings.empty,
5371 .tracked_insts = Local.TrackedInsts.empty,5429 .tracked_insts = Local.TrackedInsts.empty,
5372 .files = Local.List(File).empty,5430 .files = Local.List(File).empty,
5431 .maps = Local.Maps.empty,
53735432
5374 .decls = Local.Decls.empty,5433 .decls = Local.Decls.empty,
5375 .namespaces = Local.Namespaces.empty,5434 .namespaces = Local.Namespaces.empty,
...@@ -5383,6 +5442,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -5383,6 +5442,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
5383 .strings = Local.ListMutate.empty,5442 .strings = Local.ListMutate.empty,
5384 .tracked_insts = Local.MutexListMutate.empty,5443 .tracked_insts = Local.MutexListMutate.empty,
5385 .files = Local.ListMutate.empty,5444 .files = Local.ListMutate.empty,
5445 .maps = Local.ListMutate.empty,
53865446
5387 .decls = Local.BucketListMutate.empty,5447 .decls = Local.BucketListMutate.empty,
5388 .namespaces = Local.BucketListMutate.empty,5448 .namespaces = Local.BucketListMutate.empty,
...@@ -5440,9 +5500,6 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -5440,9 +5500,6 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
5440}5500}
54415501
5442pub fn deinit(ip: *InternPool, gpa: Allocator) void {5502pub fn deinit(ip: *InternPool, gpa: Allocator) void {
5443 for (ip.maps.items) |*map| map.deinit(gpa);
5444 ip.maps.deinit(gpa);
5445
5446 ip.src_hash_deps.deinit(gpa);5503 ip.src_hash_deps.deinit(gpa);
5447 ip.decl_val_deps.deinit(gpa);5504 ip.decl_val_deps.deinit(gpa);
5448 ip.func_ies_deps.deinit(gpa);5505 ip.func_ies_deps.deinit(gpa);
...@@ -5470,6 +5527,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -5470,6 +5527,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
5470 namespace.usingnamespace_set.deinit(gpa);5527 namespace.usingnamespace_set.deinit(gpa);
5471 }5528 }
5472 };5529 };
5530 const maps = local.getMutableMaps(gpa);
5531 if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa);
5473 local.mutate.arena.promote(gpa).deinit();5532 local.mutate.arena.promote(gpa).deinit();
5474 }5533 }
5475 gpa.free(ip.locals);5534 gpa.free(ip.locals);
...@@ -6386,8 +6445,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -6386,8 +6445,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
6386 assert(error_set_type.names_map == .none);6445 assert(error_set_type.names_map == .none);
6387 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan));6446 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan));
6388 const names = error_set_type.names.get(ip);6447 const names = error_set_type.names.get(ip);
6389 const names_map = try ip.addMap(gpa, names.len);6448 const names_map = try ip.addMap(gpa, tid, names.len);
6390 addStringsToMap(ip, names_map, names);6449 ip.addStringsToMap(names_map, names);
6391 const names_len = error_set_type.names.len;6450 const names_len = error_set_type.names.len;
6392 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).Struct.fields.len + names_len);6451 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).Struct.fields.len + names_len);
6393 items.appendAssumeCapacity(.{6452 items.appendAssumeCapacity(.{
...@@ -7287,8 +7346,8 @@ pub fn getStructType(...@@ -7287,8 +7346,8 @@ pub fn getStructType(
7287 const items = local.getMutableItems(gpa);7346 const items = local.getMutableItems(gpa);
7288 const extra = local.getMutableExtra(gpa);7347 const extra = local.getMutableExtra(gpa);
72897348
7290 const names_map = try ip.addMap(gpa, ini.fields_len);7349 const names_map = try ip.addMap(gpa, tid, ini.fields_len);
7291 errdefer _ = ip.maps.pop();7350 errdefer local.mutate.maps.len -= 1;
72927351
7293 const zir_index = switch (ini.key) {7352 const zir_index = switch (ini.key) {
7294 inline else => |x| x.zir_index,7353 inline else => |x| x.zir_index,
...@@ -7835,17 +7894,18 @@ pub fn getErrorSetType(...@@ -7835,17 +7894,18 @@ pub fn getErrorSetType(
7835 const extra = local.getMutableExtra(gpa);7894 const extra = local.getMutableExtra(gpa);
7836 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).Struct.fields.len + names.len);7895 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).Struct.fields.len + names.len);
78377896
7897 const names_map = try ip.addMap(gpa, tid, names.len);
7898 errdefer local.mutate.maps.len -= 1;
7899
7838 // The strategy here is to add the type unconditionally, then to ask if it7900 // The strategy here is to add the type unconditionally, then to ask if it
7839 // already exists, and if so, revert the lengths of the mutated arrays.7901 // already exists, and if so, revert the lengths of the mutated arrays.
7840 // This is similar to what `getOrPutTrailingString` does.7902 // This is similar to what `getOrPutTrailingString` does.
7841 const prev_extra_len = extra.mutate.len;7903 const prev_extra_len = extra.mutate.len;
7842 errdefer extra.mutate.len = prev_extra_len;7904 errdefer extra.mutate.len = prev_extra_len;
78437905
7844 const predicted_names_map: MapIndex = @enumFromInt(ip.maps.items.len);
7845
7846 const error_set_extra_index = addExtraAssumeCapacity(extra, Tag.ErrorSet{7906 const error_set_extra_index = addExtraAssumeCapacity(extra, Tag.ErrorSet{
7847 .names_len = @intCast(names.len),7907 .names_len = @intCast(names.len),
7848 .names_map = predicted_names_map,7908 .names_map = names_map,
7849 });7909 });
7850 extra.appendSliceAssumeCapacity(.{@ptrCast(names)});7910 extra.appendSliceAssumeCapacity(.{@ptrCast(names)});
7851 errdefer extra.mutate.len = prev_extra_len;7911 errdefer extra.mutate.len = prev_extra_len;
...@@ -7865,11 +7925,7 @@ pub fn getErrorSetType(...@@ -7865,11 +7925,7 @@ pub fn getErrorSetType(
7865 });7925 });
7866 errdefer items.mutate.len -= 1;7926 errdefer items.mutate.len -= 1;
78677927
7868 const names_map = try ip.addMap(gpa, names.len);7928 ip.addStringsToMap(names_map, names);
7869 assert(names_map == predicted_names_map);
7870 errdefer _ = ip.maps.pop();
7871
7872 addStringsToMap(ip, names_map, names);
78737929
7874 return gop.put();7930 return gop.put();
7875}7931}
...@@ -8235,7 +8291,7 @@ pub const WipEnumType = struct {...@@ -8235,7 +8291,7 @@ pub const WipEnumType = struct {
8235 return null;8291 return null;
8236 }8292 }
8237 assert(ip.typeOf(value) == @as(Index, @enumFromInt(extra_items[wip.tag_ty_index])));8293 assert(ip.typeOf(value) == @as(Index, @enumFromInt(extra_items[wip.tag_ty_index])));
8238 const map = &ip.maps.items[@intFromEnum(wip.values_map.unwrap().?)];8294 const map = wip.values_map.unwrap().?.get(ip);
8239 const field_index = map.count();8295 const field_index = map.count();
8240 const indexes = extra_items[wip.values_start..][0..field_index];8296 const indexes = extra_items[wip.values_start..][0..field_index];
8241 const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) };8297 const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) };
...@@ -8281,8 +8337,8 @@ pub fn getEnumType(...@@ -8281,8 +8337,8 @@ pub fn getEnumType(
8281 try items.ensureUnusedCapacity(1);8337 try items.ensureUnusedCapacity(1);
8282 const extra = local.getMutableExtra(gpa);8338 const extra = local.getMutableExtra(gpa);
82838339
8284 const names_map = try ip.addMap(gpa, ini.fields_len);8340 const names_map = try ip.addMap(gpa, tid, ini.fields_len);
8285 errdefer _ = ip.maps.pop();8341 errdefer local.mutate.maps.len -= 1;
82868342
8287 switch (ini.tag_mode) {8343 switch (ini.tag_mode) {
8288 .auto => {8344 .auto => {
...@@ -8335,11 +8391,11 @@ pub fn getEnumType(...@@ -8335,11 +8391,11 @@ pub fn getEnumType(
8335 },8391 },
8336 .explicit, .nonexhaustive => {8392 .explicit, .nonexhaustive => {
8337 const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: {8393 const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: {
8338 const values_map = try ip.addMap(gpa, ini.fields_len);8394 const values_map = try ip.addMap(gpa, tid, ini.fields_len);
8339 break :m values_map.toOptional();8395 break :m values_map.toOptional();
8340 };8396 };
8341 errdefer if (ini.has_values) {8397 errdefer if (ini.has_values) {
8342 _ = ip.maps.pop();8398 local.mutate.maps.len -= 1;
8343 };8399 };
83448400
8345 try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).Struct.fields.len +8401 try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).Struct.fields.len +
...@@ -8428,8 +8484,8 @@ pub fn getGeneratedTagEnumType(...@@ -8428,8 +8484,8 @@ pub fn getGeneratedTagEnumType(
8428 try items.ensureUnusedCapacity(1);8484 try items.ensureUnusedCapacity(1);
8429 const extra = local.getMutableExtra(gpa);8485 const extra = local.getMutableExtra(gpa);
84308486
8431 const names_map = try ip.addMap(gpa, ini.names.len);8487 const names_map = try ip.addMap(gpa, tid, ini.names.len);
8432 errdefer _ = ip.maps.pop();8488 errdefer local.mutate.maps.len -= 1;
8433 ip.addStringsToMap(names_map, ini.names);8489 ip.addStringsToMap(names_map, ini.names);
84348490
8435 const fields_len: u32 = @intCast(ini.names.len);8491 const fields_len: u32 = @intCast(ini.names.len);
...@@ -8462,8 +8518,8 @@ pub fn getGeneratedTagEnumType(...@@ -8462,8 +8518,8 @@ pub fn getGeneratedTagEnumType(
8462 ini.values.len); // field values8518 ini.values.len); // field values
84638519
8464 const values_map: OptionalMapIndex = if (ini.values.len != 0) m: {8520 const values_map: OptionalMapIndex = if (ini.values.len != 0) m: {
8465 const map = try ip.addMap(gpa, ini.values.len);8521 const map = try ip.addMap(gpa, tid, ini.values.len);
8466 addIndexesToMap(ip, map, ini.values);8522 ip.addIndexesToMap(map, ini.values);
8467 break :m map.toOptional();8523 break :m map.toOptional();
8468 } else .none;8524 } else .none;
8469 // We don't clean up the values map on error!8525 // We don't clean up the values map on error!
...@@ -8494,7 +8550,9 @@ pub fn getGeneratedTagEnumType(...@@ -8494,7 +8550,9 @@ pub fn getGeneratedTagEnumType(
8494 errdefer extra.mutate.len = prev_extra_len;8550 errdefer extra.mutate.len = prev_extra_len;
8495 errdefer switch (ini.tag_mode) {8551 errdefer switch (ini.tag_mode) {
8496 .auto => {},8552 .auto => {},
8497 .explicit, .nonexhaustive => _ = if (ini.values.len != 0) ip.maps.pop(),8553 .explicit, .nonexhaustive => if (ini.values.len != 0) {
8554 local.mutate.maps.len -= 1;
8555 },
8498 };8556 };
84998557
8500 var gop = try ip.getOrPutKey(gpa, tid, .{ .enum_type = .{8558 var gop = try ip.getOrPutKey(gpa, tid, .{ .enum_type = .{
...@@ -8598,7 +8656,7 @@ fn addStringsToMap(...@@ -8598,7 +8656,7 @@ fn addStringsToMap(
8598 map_index: MapIndex,8656 map_index: MapIndex,
8599 strings: []const NullTerminatedString,8657 strings: []const NullTerminatedString,
8600) void {8658) void {
8601 const map = &ip.maps.items[@intFromEnum(map_index)];8659 const map = map_index.get(ip);
8602 const adapter: NullTerminatedString.Adapter = .{ .strings = strings };8660 const adapter: NullTerminatedString.Adapter = .{ .strings = strings };
8603 for (strings) |string| {8661 for (strings) |string| {
8604 const gop = map.getOrPutAssumeCapacityAdapted(string, adapter);8662 const gop = map.getOrPutAssumeCapacityAdapted(string, adapter);
...@@ -8611,7 +8669,7 @@ fn addIndexesToMap(...@@ -8611,7 +8669,7 @@ fn addIndexesToMap(
8611 map_index: MapIndex,8669 map_index: MapIndex,
8612 indexes: []const Index,8670 indexes: []const Index,
8613) void {8671) void {
8614 const map = &ip.maps.items[@intFromEnum(map_index)];8672 const map = map_index.get(ip);
8615 const adapter: Index.Adapter = .{ .indexes = indexes };8673 const adapter: Index.Adapter = .{ .indexes = indexes };
8616 for (indexes) |index| {8674 for (indexes) |index| {
8617 const gop = map.getOrPutAssumeCapacityAdapted(index, adapter);8675 const gop = map.getOrPutAssumeCapacityAdapted(index, adapter);
...@@ -8619,12 +8677,14 @@ fn addIndexesToMap(...@@ -8619,12 +8677,14 @@ fn addIndexesToMap(
8619 }8677 }
8620}8678}
86218679
8622fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex {8680fn addMap(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex {
8623 const ptr = try ip.maps.addOne(gpa);8681 const maps = ip.getLocal(tid).getMutableMaps(gpa);
8624 errdefer _ = ip.maps.pop();8682 const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len };
8625 ptr.* = .{};8683 const ptr = try maps.addOne();
8626 try ptr.ensureTotalCapacity(gpa, cap);8684 errdefer maps.mutate.len = unwrapped.index;
8627 return @enumFromInt(ip.maps.items.len - 1);8685 ptr[0].* = .{};
8686 try ptr[0].ensureTotalCapacity(gpa, cap);
8687 return unwrapped.wrap(ip);
8628}8688}
86298689
8630/// This operation only happens under compile error conditions.8690/// This operation only happens under compile error conditions.
...@@ -10858,7 +10918,7 @@ pub fn addFieldName(...@@ -10858,7 +10918,7 @@ pub fn addFieldName(
10858 name: NullTerminatedString,10918 name: NullTerminatedString,
10859) ?u32 {10919) ?u32 {
10860 const extra_items = extra.view().items(.@"0");10920 const extra_items = extra.view().items(.@"0");
10861 const map = &ip.maps.items[@intFromEnum(names_map)];10921 const map = names_map.get(ip);
10862 const field_index = map.count();10922 const field_index = map.count();
10863 const strings = extra_items[names_start..][0..field_index];10923 const strings = extra_items[names_start..][0..field_index];
10864 const adapter: NullTerminatedString.Adapter = .{ .strings = @ptrCast(strings) };10924 const adapter: NullTerminatedString.Adapter = .{ .strings = @ptrCast(strings) };