authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-16 14:49:49-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-16 14:49:49-04:00
log88bb0fd288acb6a20abed57cdf459cc4fc788b89
tree4a488eb0c9ef76f63d13d12de1649ddab9b8caac
parentd8f81372f148ad2ee5aab12cc7ea55562764b3e7
parent00fdbf05f39931d1f6c5808e8da4afca85357214
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20632 from jacobly0/codegen-thread

InternPool: enable separate codegen/linking thread

6 files changed, 114 insertions(+), 63 deletions(-)

lib/std/Progress.zig+1-7
...@@ -669,14 +669,8 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {...@@ -669,14 +669,8 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {
669fn clearWrittenWithEscapeCodes() anyerror!void {669fn clearWrittenWithEscapeCodes() anyerror!void {
670 if (!global_progress.need_clear) return;670 if (!global_progress.need_clear) return;
671671
672 var i: usize = 0;
673 const buf = global_progress.draw_buffer;
674
675 buf[i..][0..clear.len].* = clear.*;
676 i += clear.len;
677
678 global_progress.need_clear = false;672 global_progress.need_clear = false;
679 try write(buf[0..i]);673 try write(clear);
680}674}
681675
682/// U+25BA or ►676/// U+25BA or ►
lib/std/mem.zig+6-5
...@@ -1050,15 +1050,16 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co...@@ -1050,15 +1050,16 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co
1050 // as we don't read into a new page. This should be the case for most architectures1050 // as we don't read into a new page. This should be the case for most architectures
1051 // which use paged memory, however should be confirmed before adding a new arch below.1051 // which use paged memory, however should be confirmed before adding a new arch below.
1052 .aarch64, .x86, .x86_64 => if (std.simd.suggestVectorLength(T)) |block_len| {1052 .aarch64, .x86, .x86_64 => if (std.simd.suggestVectorLength(T)) |block_len| {
1053 const block_size = @sizeOf(T) * block_len;
1053 const Block = @Vector(block_len, T);1054 const Block = @Vector(block_len, T);
1054 const mask: Block = @splat(sentinel);1055 const mask: Block = @splat(sentinel);
10551056
1056 comptime std.debug.assert(std.mem.page_size % @sizeOf(Block) == 0);1057 comptime std.debug.assert(std.mem.page_size % block_size == 0);
10571058
1058 // First block may be unaligned1059 // First block may be unaligned
1059 const start_addr = @intFromPtr(&p[i]);1060 const start_addr = @intFromPtr(&p[i]);
1060 const offset_in_page = start_addr & (std.mem.page_size - 1);1061 const offset_in_page = start_addr & (std.mem.page_size - 1);
1061 if (offset_in_page <= std.mem.page_size - @sizeOf(Block)) {1062 if (offset_in_page <= std.mem.page_size - block_size) {
1062 // Will not read past the end of a page, full block.1063 // Will not read past the end of a page, full block.
1063 const block: Block = p[i..][0..block_len].*;1064 const block: Block = p[i..][0..block_len].*;
1064 const matches = block == mask;1065 const matches = block == mask;
...@@ -1066,19 +1067,19 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co...@@ -1066,19 +1067,19 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co
1066 return i + std.simd.firstTrue(matches).?;1067 return i + std.simd.firstTrue(matches).?;
1067 }1068 }
10681069
1069 i += (std.mem.alignForward(usize, start_addr, @alignOf(Block)) - start_addr) / @sizeOf(T);1070 i += @divExact(std.mem.alignForward(usize, start_addr, block_size) - start_addr, @sizeOf(T));
1070 } else {1071 } else {
1071 // Would read over a page boundary. Per-byte at a time until aligned or found.1072 // Would read over a page boundary. Per-byte at a time until aligned or found.
1072 // 0.39% chance this branch is taken for 4K pages at 16b block length.1073 // 0.39% chance this branch is taken for 4K pages at 16b block length.
1073 //1074 //
1074 // An alternate strategy is to do read a full block (the last in the page) and1075 // An alternate strategy is to do read a full block (the last in the page) and
1075 // mask the entries before the pointer.1076 // mask the entries before the pointer.
1076 while ((@intFromPtr(&p[i]) & (@alignOf(Block) - 1)) != 0) : (i += 1) {1077 while ((@intFromPtr(&p[i]) & (block_size - 1)) != 0) : (i += 1) {
1077 if (p[i] == sentinel) return i;1078 if (p[i] == sentinel) return i;
1078 }1079 }
1079 }1080 }
10801081
1081 std.debug.assert(std.mem.isAligned(@intFromPtr(&p[i]), @alignOf(Block)));1082 std.debug.assert(std.mem.isAligned(@intFromPtr(&p[i]), block_size));
1082 while (true) {1083 while (true) {
1083 const block: *const Block = @ptrCast(@alignCast(p[i..][0..block_len]));1084 const block: *const Block = @ptrCast(@alignCast(p[i..][0..block_len]));
1084 const matches = block.* == mask;1085 const matches = block.* == mask;
src/InternPool.zig+100-46
...@@ -10,6 +10,8 @@ shards: []Shard = &.{},...@@ -10,6 +10,8 @@ shards: []Shard = &.{},
10global_error_set: GlobalErrorSet = GlobalErrorSet.empty,10global_error_set: GlobalErrorSet = GlobalErrorSet.empty,
11/// Cached number of active bits in a `tid`.11/// Cached number of active bits in a `tid`.
12tid_width: if (single_threaded) u0 else std.math.Log2Int(u32) = 0,12tid_width: if (single_threaded) u0 else std.math.Log2Int(u32) = 0,
13/// Cached shift amount to put a `tid` in the top bits of a 30-bit value.
14tid_shift_30: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31,
13/// Cached shift amount to put a `tid` in the top bits of a 31-bit value.15/// Cached shift amount to put a `tid` in the top bits of a 31-bit value.
14tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31,16tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31,
15/// Cached shift amount to put a `tid` in the top bits of a 32-bit value.17/// Cached shift amount to put a `tid` in the top bits of a 32-bit value.
...@@ -53,7 +55,7 @@ free_dep_entries: std.ArrayListUnmanaged(DepEntry.Index) = .{},...@@ -53,7 +55,7 @@ free_dep_entries: std.ArrayListUnmanaged(DepEntry.Index) = .{},
53/// Whether a multi-threaded intern pool is useful.55/// Whether a multi-threaded intern pool is useful.
54/// Currently `false` until the intern pool is actually accessed56/// Currently `false` until the intern pool is actually accessed
55/// from multiple threads to reduce the cost of this data structure.57/// from multiple threads to reduce the cost of this data structure.
56const want_multi_threaded = false;58const want_multi_threaded = true;
5759
58/// Whether a single-threaded intern pool impl is in use.60/// Whether a single-threaded intern pool impl is in use.
59pub const single_threaded = builtin.single_threaded or !want_multi_threaded;61pub const single_threaded = builtin.single_threaded or !want_multi_threaded;
...@@ -941,8 +943,12 @@ const Shard = struct {...@@ -941,8 +943,12 @@ const Shard = struct {
941 return @atomicLoad(Value, &entry.value, .acquire);943 return @atomicLoad(Value, &entry.value, .acquire);
942 }944 }
943 fn release(entry: *Entry, value: Value) void {945 fn release(entry: *Entry, value: Value) void {
946 assert(value != .none);
944 @atomicStore(Value, &entry.value, value, .release);947 @atomicStore(Value, &entry.value, value, .release);
945 }948 }
949 fn resetUnordered(entry: *Entry) void {
950 @atomicStore(Value, &entry.value, .none, .unordered);
951 }
946 };952 };
947 };953 };
948 }954 }
...@@ -4089,8 +4095,8 @@ pub const Index = enum(u32) {...@@ -4089,8 +4095,8 @@ pub const Index = enum(u32) {
40894095
4090 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Index {4096 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Index {
4091 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());4097 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
4092 assert(unwrapped.index <= ip.getIndexMask(u31));4098 assert(unwrapped.index <= ip.getIndexMask(u30));
4093 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 | unwrapped.index);4099 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_30 | unwrapped.index);
4094 }4100 }
40954101
4096 pub fn getExtra(unwrapped: Unwrapped, ip: *const InternPool) Local.Extra {4102 pub fn getExtra(unwrapped: Unwrapped, ip: *const InternPool) Local.Extra {
...@@ -4129,8 +4135,8 @@ pub const Index = enum(u32) {...@@ -4129,8 +4135,8 @@ pub const Index = enum(u32) {
4129 .tid = .main,4135 .tid = .main,
4130 .index = @intFromEnum(index),4136 .index = @intFromEnum(index),
4131 } else .{4137 } else .{
4132 .tid = @enumFromInt(@intFromEnum(index) >> ip.tid_shift_31 & ip.getTidMask()),4138 .tid = @enumFromInt(@intFromEnum(index) >> ip.tid_shift_30 & ip.getTidMask()),
4133 .index = @intFromEnum(index) & ip.getIndexMask(u31),4139 .index = @intFromEnum(index) & ip.getIndexMask(u30),
4134 };4140 };
4135 }4141 }
41364142
...@@ -5820,6 +5826,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -5820,6 +5826,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
5820 });5826 });
58215827
5822 ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads));5828 ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads));
5829 ip.tid_shift_30 = if (single_threaded) 0 else 30 - ip.tid_width;
5823 ip.tid_shift_31 = if (single_threaded) 0 else 31 - ip.tid_width;5830 ip.tid_shift_31 = if (single_threaded) 0 else 31 - ip.tid_width;
5824 ip.tid_shift_32 = if (single_threaded) 0 else ip.tid_shift_31 +| 1;5831 ip.tid_shift_32 = if (single_threaded) 0 else ip.tid_shift_31 +| 1;
5825 ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width);5832 ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width);
...@@ -6585,35 +6592,55 @@ const GetOrPutKey = union(enum) {...@@ -6585,35 +6592,55 @@ const GetOrPutKey = union(enum) {
6585 },6592 },
65866593
6587 fn put(gop: *GetOrPutKey) Index {6594 fn put(gop: *GetOrPutKey) Index {
6588 return gop.putAt(0);
6589 }
6590 fn putAt(gop: *GetOrPutKey, offset: u32) Index {
6591 switch (gop.*) {6595 switch (gop.*) {
6592 .existing => unreachable,6596 .existing => unreachable,
6593 .new => |info| {6597 .new => |*info| {
6594 const index = Index.Unwrapped.wrap(.{6598 const index = Index.Unwrapped.wrap(.{
6595 .tid = info.tid,6599 .tid = info.tid,
6596 .index = info.ip.getLocal(info.tid).mutate.items.len - 1 - offset,6600 .index = info.ip.getLocal(info.tid).mutate.items.len - 1,
6597 }, info.ip);6601 }, info.ip);
6598 info.shard.shared.map.entries[info.map_index].release(index);6602 gop.putTentative(index);
6603 gop.putFinal(index);
6604 return index;
6605 },
6606 }
6607 }
6608
6609 fn putTentative(gop: *GetOrPutKey, index: Index) void {
6610 assert(index != .none);
6611 switch (gop.*) {
6612 .existing => unreachable,
6613 .new => |*info| gop.new.shard.shared.map.entries[info.map_index].release(index),
6614 }
6615 }
6616
6617 fn putFinal(gop: *GetOrPutKey, index: Index) void {
6618 assert(index != .none);
6619 switch (gop.*) {
6620 .existing => unreachable,
6621 .new => |info| {
6622 assert(info.shard.shared.map.entries[info.map_index].value == index);
6599 info.shard.mutate.map.len += 1;6623 info.shard.mutate.map.len += 1;
6600 info.shard.mutate.map.mutex.unlock();6624 info.shard.mutate.map.mutex.unlock();
6601 gop.* = .{ .existing = index };6625 gop.* = .{ .existing = index };
6602 return index;
6603 },6626 },
6604 }6627 }
6605 }6628 }
66066629
6607 fn assign(gop: *GetOrPutKey, new_gop: GetOrPutKey) void {6630 fn cancel(gop: *GetOrPutKey) void {
6608 gop.deinit();6631 switch (gop.*) {
6609 gop.* = new_gop;6632 .existing => {},
6633 .new => |info| info.shard.mutate.map.mutex.unlock(),
6634 }
6635 gop.* = .{ .existing = undefined };
6610 }6636 }
66116637
6612 fn deinit(gop: *GetOrPutKey) void {6638 fn deinit(gop: *GetOrPutKey) void {
6613 switch (gop.*) {6639 switch (gop.*) {
6614 .existing => {},6640 .existing => {},
6615 .new => |info| info.shard.mutate.map.mutex.unlock(),6641 .new => |info| info.shard.shared.map.entries[info.map_index].resetUnordered(),
6616 }6642 }
6643 gop.cancel();
6617 gop.* = undefined;6644 gop.* = undefined;
6618 }6645 }
6619};6646};
...@@ -6622,6 +6649,15 @@ fn getOrPutKey(...@@ -6622,6 +6649,15 @@ fn getOrPutKey(
6622 gpa: Allocator,6649 gpa: Allocator,
6623 tid: Zcu.PerThread.Id,6650 tid: Zcu.PerThread.Id,
6624 key: Key,6651 key: Key,
6652) Allocator.Error!GetOrPutKey {
6653 return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, key, 0);
6654}
6655fn getOrPutKeyEnsuringAdditionalCapacity(
6656 ip: *InternPool,
6657 gpa: Allocator,
6658 tid: Zcu.PerThread.Id,
6659 key: Key,
6660 additional_capacity: u32,
6625) Allocator.Error!GetOrPutKey {6661) Allocator.Error!GetOrPutKey {
6626 const full_hash = key.hash64(ip);6662 const full_hash = key.hash64(ip);
6627 const hash: u32 = @truncate(full_hash >> 32);6663 const hash: u32 = @truncate(full_hash >> 32);
...@@ -6657,11 +6693,16 @@ fn getOrPutKey(...@@ -6657,11 +6693,16 @@ fn getOrPutKey(
6657 }6693 }
6658 }6694 }
6659 const map_header = map.header().*;6695 const map_header = map.header().*;
6660 if (shard.mutate.map.len >= map_header.capacity * 3 / 5) {6696 const required = shard.mutate.map.len + additional_capacity;
6697 if (required >= map_header.capacity * 3 / 5) {
6661 const arena_state = &ip.getLocal(tid).mutate.arena;6698 const arena_state = &ip.getLocal(tid).mutate.arena;
6662 var arena = arena_state.promote(gpa);6699 var arena = arena_state.promote(gpa);
6663 defer arena_state.* = arena.state;6700 defer arena_state.* = arena.state;
6664 const new_map_capacity = map_header.capacity * 2;6701 var new_map_capacity = map_header.capacity;
6702 while (true) {
6703 new_map_capacity *= 2;
6704 if (required < new_map_capacity * 3 / 5) break;
6705 }
6665 const new_map_buf = try arena.allocator().alignedAlloc(6706 const new_map_buf = try arena.allocator().alignedAlloc(
6666 u8,6707 u8,
6667 Map.alignment,6708 Map.alignment,
...@@ -6730,10 +6771,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -6730,10 +6771,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
6730 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child);6771 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child);
67316772
6732 if (ptr_type.flags.size == .Slice) {6773 if (ptr_type.flags.size == .Slice) {
6774 gop.cancel();
6733 var new_key = key;6775 var new_key = key;
6734 new_key.ptr_type.flags.size = .Many;6776 new_key.ptr_type.flags.size = .Many;
6735 const ptr_type_index = try ip.get(gpa, tid, new_key);6777 const ptr_type_index = try ip.get(gpa, tid, new_key);
6736 gop.assign(try ip.getOrPutKey(gpa, tid, key));6778 gop = try ip.getOrPutKey(gpa, tid, key);
67376779
6738 try items.ensureUnusedCapacity(1);6780 try items.ensureUnusedCapacity(1);
6739 items.appendAssumeCapacity(.{6781 items.appendAssumeCapacity(.{
...@@ -6913,9 +6955,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -6913,9 +6955,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
6913 },6955 },
6914 .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: {6956 .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: {
6915 if (ptr.ty != anon_decl.orig_ty) {6957 if (ptr.ty != anon_decl.orig_ty) {
6958 gop.cancel();
6916 var new_key = key;6959 var new_key = key;
6917 new_key.ptr.base_addr.anon_decl.orig_ty = ptr.ty;6960 new_key.ptr.base_addr.anon_decl.orig_ty = ptr.ty;
6918 gop.assign(try ip.getOrPutKey(gpa, tid, new_key));6961 gop = try ip.getOrPutKey(gpa, tid, new_key);
6919 if (gop == .existing) return gop.existing;6962 if (gop == .existing) return gop.existing;
6920 }6963 }
6921 break :item .{6964 break :item .{
...@@ -6986,11 +7029,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -6986,11 +7029,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
6986 },7029 },
6987 else => unreachable,7030 else => unreachable,
6988 }7031 }
7032 gop.cancel();
6989 const index_index = try ip.get(gpa, tid, .{ .int = .{7033 const index_index = try ip.get(gpa, tid, .{ .int = .{
6990 .ty = .usize_type,7034 .ty = .usize_type,
6991 .storage = .{ .u64 = base_index.index },7035 .storage = .{ .u64 = base_index.index },
6992 } });7036 } });
6993 gop.assign(try ip.getOrPutKey(gpa, tid, key));7037 gop = try ip.getOrPutKey(gpa, tid, key);
6994 try items.ensureUnusedCapacity(1);7038 try items.ensureUnusedCapacity(1);
6995 items.appendAssumeCapacity(.{7039 items.appendAssumeCapacity(.{
6996 .tag = switch (ptr.base_addr) {7040 .tag = switch (ptr.base_addr) {
...@@ -7399,11 +7443,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7399,11 +7443,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7399 }7443 }
7400 const elem = switch (aggregate.storage) {7444 const elem = switch (aggregate.storage) {
7401 .bytes => |bytes| elem: {7445 .bytes => |bytes| elem: {
7446 gop.cancel();
7402 const elem = try ip.get(gpa, tid, .{ .int = .{7447 const elem = try ip.get(gpa, tid, .{ .int = .{
7403 .ty = .u8_type,7448 .ty = .u8_type,
7404 .storage = .{ .u64 = bytes.at(0, ip) },7449 .storage = .{ .u64 = bytes.at(0, ip) },
7405 } });7450 } });
7406 gop.assign(try ip.getOrPutKey(gpa, tid, key));7451 gop = try ip.getOrPutKey(gpa, tid, key);
7407 try items.ensureUnusedCapacity(1);7452 try items.ensureUnusedCapacity(1);
7408 break :elem elem;7453 break :elem elem;
7409 },7454 },
...@@ -8221,9 +8266,9 @@ pub fn getFuncDeclIes(...@@ -8221,9 +8266,9 @@ pub fn getFuncDeclIes(
8221 extra.mutate.len = prev_extra_len;8266 extra.mutate.len = prev_extra_len;
8222 }8267 }
82238268
8224 var func_gop = try ip.getOrPutKey(gpa, tid, .{8269 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{
8225 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),8270 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),
8226 });8271 }, 3);
8227 defer func_gop.deinit();8272 defer func_gop.deinit();
8228 if (func_gop == .existing) {8273 if (func_gop == .existing) {
8229 // An existing function type was found; undo the additions to our two arrays.8274 // An existing function type was found; undo the additions to our two arrays.
...@@ -8231,23 +8276,28 @@ pub fn getFuncDeclIes(...@@ -8231,23 +8276,28 @@ pub fn getFuncDeclIes(
8231 extra.mutate.len = prev_extra_len;8276 extra.mutate.len = prev_extra_len;
8232 return func_gop.existing;8277 return func_gop.existing;
8233 }8278 }
8234 var error_union_type_gop = try ip.getOrPutKey(gpa, tid, .{ .error_union_type = .{8279 func_gop.putTentative(func_index);
8280 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{
8235 .error_set_type = error_set_type,8281 .error_set_type = error_set_type,
8236 .payload_type = key.bare_return_type,8282 .payload_type = key.bare_return_type,
8237 } });8283 } }, 2);
8238 defer error_union_type_gop.deinit();8284 defer error_union_type_gop.deinit();
8239 var error_set_type_gop = try ip.getOrPutKey(gpa, tid, .{8285 error_union_type_gop.putTentative(error_union_type);
8286 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{
8240 .inferred_error_set_type = func_index,8287 .inferred_error_set_type = func_index,
8241 });8288 }, 1);
8242 defer error_set_type_gop.deinit();8289 defer error_set_type_gop.deinit();
8290 error_set_type_gop.putTentative(error_set_type);
8243 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{8291 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{
8244 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),8292 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
8245 });8293 });
8246 defer func_ty_gop.deinit();8294 defer func_ty_gop.deinit();
8247 assert(func_gop.putAt(3) == func_index);8295 func_ty_gop.putTentative(func_ty);
8248 assert(error_union_type_gop.putAt(2) == error_union_type);8296
8249 assert(error_set_type_gop.putAt(1) == error_set_type);8297 func_gop.putFinal(func_index);
8250 assert(func_ty_gop.putAt(0) == func_ty);8298 error_union_type_gop.putFinal(error_union_type);
8299 error_set_type_gop.putFinal(error_set_type);
8300 func_ty_gop.putFinal(func_ty);
8251 return func_index;8301 return func_index;
8252}8302}
82538303
...@@ -8506,9 +8556,9 @@ pub fn getFuncInstanceIes(...@@ -8506,9 +8556,9 @@ pub fn getFuncInstanceIes(
8506 extra.mutate.len = prev_extra_len;8556 extra.mutate.len = prev_extra_len;
8507 }8557 }
85088558
8509 var func_gop = try ip.getOrPutKey(gpa, tid, .{8559 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{
8510 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),8560 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),
8511 });8561 }, 3);
8512 defer func_gop.deinit();8562 defer func_gop.deinit();
8513 if (func_gop == .existing) {8563 if (func_gop == .existing) {
8514 // Hot path: undo the additions to our two arrays.8564 // Hot path: undo the additions to our two arrays.
...@@ -8516,19 +8566,23 @@ pub fn getFuncInstanceIes(...@@ -8516,19 +8566,23 @@ pub fn getFuncInstanceIes(
8516 extra.mutate.len = prev_extra_len;8566 extra.mutate.len = prev_extra_len;
8517 return func_gop.existing;8567 return func_gop.existing;
8518 }8568 }
8519 var error_union_type_gop = try ip.getOrPutKey(gpa, tid, .{ .error_union_type = .{8569 func_gop.putTentative(func_index);
8570 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{
8520 .error_set_type = error_set_type,8571 .error_set_type = error_set_type,
8521 .payload_type = arg.bare_return_type,8572 .payload_type = arg.bare_return_type,
8522 } });8573 } }, 2);
8523 defer error_union_type_gop.deinit();8574 defer error_union_type_gop.deinit();
8524 var error_set_type_gop = try ip.getOrPutKey(gpa, tid, .{8575 error_union_type_gop.putTentative(error_union_type);
8576 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{
8525 .inferred_error_set_type = func_index,8577 .inferred_error_set_type = func_index,
8526 });8578 }, 1);
8527 defer error_set_type_gop.deinit();8579 defer error_set_type_gop.deinit();
8580 error_set_type_gop.putTentative(error_set_type);
8528 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{8581 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{
8529 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),8582 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
8530 });8583 });
8531 defer func_ty_gop.deinit();8584 defer func_ty_gop.deinit();
8585 func_ty_gop.putTentative(func_ty);
8532 try finishFuncInstance(8586 try finishFuncInstance(
8533 ip,8587 ip,
8534 gpa,8588 gpa,
...@@ -8540,10 +8594,11 @@ pub fn getFuncInstanceIes(...@@ -8540,10 +8594,11 @@ pub fn getFuncInstanceIes(
8540 arg.alignment,8594 arg.alignment,
8541 arg.section,8595 arg.section,
8542 );8596 );
8543 assert(func_gop.putAt(3) == func_index);8597
8544 assert(error_union_type_gop.putAt(2) == error_union_type);8598 func_gop.putFinal(func_index);
8545 assert(error_set_type_gop.putAt(1) == error_set_type);8599 error_union_type_gop.putFinal(error_union_type);
8546 assert(func_ty_gop.putAt(0) == func_ty);8600 error_set_type_gop.putFinal(error_set_type);
8601 func_ty_gop.putFinal(func_ty);
8547 return func_index;8602 return func_index;
8548}8603}
85498604
...@@ -10839,19 +10894,18 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) OptionalDeclIndex {...@@ -10839,19 +10894,18 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) OptionalDeclIndex {
10839 while (true) {10894 while (true) {
10840 const unwrapped_base = base.unwrap(ip);10895 const unwrapped_base = base.unwrap(ip);
10841 const base_item = unwrapped_base.getItem(ip);10896 const base_item = unwrapped_base.getItem(ip);
10842 const base_extra_items = unwrapped_base.getExtra(ip).view().items(.@"0");
10843 switch (base_item.tag) {10897 switch (base_item.tag) {
10844 .ptr_decl => return @enumFromInt(base_extra_items[10898 .ptr_decl => return @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[
10845 base_item.data + std.meta.fieldIndex(PtrDecl, "decl").?10899 base_item.data + std.meta.fieldIndex(PtrDecl, "decl").?
10846 ]),10900 ]),
10847 inline .ptr_eu_payload,10901 inline .ptr_eu_payload,
10848 .ptr_opt_payload,10902 .ptr_opt_payload,
10849 .ptr_elem,10903 .ptr_elem,
10850 .ptr_field,10904 .ptr_field,
10851 => |tag| base = @enumFromInt(base_extra_items[10905 => |tag| base = @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[
10852 base_item.data + std.meta.fieldIndex(tag.Payload(), "base").?10906 base_item.data + std.meta.fieldIndex(tag.Payload(), "base").?
10853 ]),10907 ]),
10854 .ptr_slice => base = @enumFromInt(base_extra_items[10908 .ptr_slice => base = @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[
10855 base_item.data + std.meta.fieldIndex(PtrSlice, "ptr").?10909 base_item.data + std.meta.fieldIndex(PtrSlice, "ptr").?
10856 ]),10910 ]),
10857 else => return .none,10911 else => return .none,
src/Zcu/PerThread.zig+2-1
...@@ -3,7 +3,8 @@ zcu: *Zcu,...@@ -3,7 +3,8 @@ zcu: *Zcu,
3/// Dense, per-thread unique index.3/// Dense, per-thread unique index.
4tid: Id,4tid: Id,
55
6pub const Id = if (InternPool.single_threaded) enum { main } else enum(u8) { main, _ };6pub const IdBacking = u7;
7pub const Id = if (InternPool.single_threaded) enum { main } else enum(IdBacking) { main, _ };
78
8pub fn destroyDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {9pub fn destroyDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {
9 const zcu = pt.zcu;10 const zcu = pt.zcu;
src/main.zig+3-3
...@@ -3110,7 +3110,7 @@ fn buildOutputType(...@@ -3110,7 +3110,7 @@ fn buildOutputType(
3110 var thread_pool: ThreadPool = undefined;3110 var thread_pool: ThreadPool = undefined;
3111 try thread_pool.init(.{3111 try thread_pool.init(.{
3112 .allocator = gpa,3112 .allocator = gpa,
3113 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(u8)),3113 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
3114 .track_ids = true,3114 .track_ids = true,
3115 });3115 });
3116 defer thread_pool.deinit();3116 defer thread_pool.deinit();
...@@ -4964,7 +4964,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4964,7 +4964,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4964 var thread_pool: ThreadPool = undefined;4964 var thread_pool: ThreadPool = undefined;
4965 try thread_pool.init(.{4965 try thread_pool.init(.{
4966 .allocator = gpa,4966 .allocator = gpa,
4967 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(u8)),4967 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
4968 .track_ids = true,4968 .track_ids = true,
4969 });4969 });
4970 defer thread_pool.deinit();4970 defer thread_pool.deinit();
...@@ -5402,7 +5402,7 @@ fn jitCmd(...@@ -5402,7 +5402,7 @@ fn jitCmd(
5402 var thread_pool: ThreadPool = undefined;5402 var thread_pool: ThreadPool = undefined;
5403 try thread_pool.init(.{5403 try thread_pool.init(.{
5404 .allocator = gpa,5404 .allocator = gpa,
5405 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(u8)),5405 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
5406 .track_ids = true,5406 .track_ids = true,
5407 });5407 });
5408 defer thread_pool.deinit();5408 defer thread_pool.deinit();
src/target.zig+2-1
...@@ -572,7 +572,8 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt...@@ -572,7 +572,8 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
572 else => false,572 else => false,
573 },573 },
574 .separate_thread => switch (backend) {574 .separate_thread => switch (backend) {
575 else => false,575 .stage2_llvm => false,
576 else => true,
576 },577 },
577 };578 };
578}579}