| ... | ... | @@ -10,6 +10,8 @@ shards: []Shard = &.{}, |
| 10 | 10 | global_error_set: GlobalErrorSet = GlobalErrorSet.empty, |
| 11 | 11 | /// Cached number of active bits in a `tid`. |
| 12 | 12 | tid_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. |
| 14 | tid_shift_30: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31, |
| 13 | 15 | /// Cached shift amount to put a `tid` in the top bits of a 31-bit value. |
| 14 | 16 | tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_threaded) 0 else 31, |
| 15 | 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 | 55 | /// Whether a multi-threaded intern pool is useful. |
| 54 | 56 | /// Currently `false` until the intern pool is actually accessed |
| 55 | 57 | /// from multiple threads to reduce the cost of this data structure. |
| 56 | | const want_multi_threaded = false; |
| 58 | const want_multi_threaded = true; |
| 57 | 59 | |
| 58 | 60 | /// Whether a single-threaded intern pool impl is in use. |
| 59 | 61 | pub const single_threaded = builtin.single_threaded or !want_multi_threaded; |
| ... | ... | @@ -941,8 +943,12 @@ const Shard = struct { |
| 941 | 943 | return @atomicLoad(Value, &entry.value, .acquire); |
| 942 | 944 | } |
| 943 | 945 | fn release(entry: *Entry, value: Value) void { |
| 946 | assert(value != .none); |
| 944 | 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 | 4095 | |
| 4090 | 4096 | fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Index { |
| 4091 | 4097 | assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask()); |
| 4092 | | assert(unwrapped.index <= ip.getIndexMask(u31)); |
| 4093 | | return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 | unwrapped.index); |
| 4098 | assert(unwrapped.index <= ip.getIndexMask(u30)); |
| 4099 | return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_30 | unwrapped.index); |
| 4094 | 4100 | } |
| 4095 | 4101 | |
| 4096 | 4102 | pub fn getExtra(unwrapped: Unwrapped, ip: *const InternPool) Local.Extra { |
| ... | ... | @@ -4129,8 +4135,8 @@ pub const Index = enum(u32) { |
| 4129 | 4135 | .tid = .main, |
| 4130 | 4136 | .index = @intFromEnum(index), |
| 4131 | 4137 | } else .{ |
| 4132 | | .tid = @enumFromInt(@intFromEnum(index) >> ip.tid_shift_31 & ip.getTidMask()), |
| 4133 | | .index = @intFromEnum(index) & ip.getIndexMask(u31), |
| 4138 | .tid = @enumFromInt(@intFromEnum(index) >> ip.tid_shift_30 & ip.getTidMask()), |
| 4139 | .index = @intFromEnum(index) & ip.getIndexMask(u30), |
| 4134 | 4140 | }; |
| 4135 | 4141 | } |
| 4136 | 4142 | |
| ... | ... | @@ -5820,6 +5826,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 5820 | 5826 | }); |
| 5821 | 5827 | |
| 5822 | 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 | 5830 | ip.tid_shift_31 = if (single_threaded) 0 else 31 - ip.tid_width; |
| 5824 | 5831 | ip.tid_shift_32 = if (single_threaded) 0 else ip.tid_shift_31 +| 1; |
| 5825 | 5832 | ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width); |
| ... | ... | @@ -6585,35 +6592,55 @@ const GetOrPutKey = union(enum) { |
| 6585 | 6592 | }, |
| 6586 | 6593 | |
| 6587 | 6594 | fn put(gop: *GetOrPutKey) Index { |
| 6588 | | return gop.putAt(0); |
| 6589 | | } |
| 6590 | | fn putAt(gop: *GetOrPutKey, offset: u32) Index { |
| 6591 | 6595 | switch (gop.*) { |
| 6592 | 6596 | .existing => unreachable, |
| 6593 | | .new => |info| { |
| 6597 | .new => |*info| { |
| 6594 | 6598 | const index = Index.Unwrapped.wrap(.{ |
| 6595 | 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 | 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 | 6623 | info.shard.mutate.map.len += 1; |
| 6600 | 6624 | info.shard.mutate.map.mutex.unlock(); |
| 6601 | 6625 | gop.* = .{ .existing = index }; |
| 6602 | | return index; |
| 6603 | 6626 | }, |
| 6604 | 6627 | } |
| 6605 | 6628 | } |
| 6606 | 6629 | |
| 6607 | | fn assign(gop: *GetOrPutKey, new_gop: GetOrPutKey) void { |
| 6608 | | gop.deinit(); |
| 6609 | | gop.* = new_gop; |
| 6630 | fn cancel(gop: *GetOrPutKey) void { |
| 6631 | switch (gop.*) { |
| 6632 | .existing => {}, |
| 6633 | .new => |info| info.shard.mutate.map.mutex.unlock(), |
| 6634 | } |
| 6635 | gop.* = .{ .existing = undefined }; |
| 6610 | 6636 | } |
| 6611 | 6637 | |
| 6612 | 6638 | fn deinit(gop: *GetOrPutKey) void { |
| 6613 | 6639 | switch (gop.*) { |
| 6614 | 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 | 6644 | gop.* = undefined; |
| 6618 | 6645 | } |
| 6619 | 6646 | }; |
| ... | ... | @@ -6622,6 +6649,15 @@ fn getOrPutKey( |
| 6622 | 6649 | gpa: Allocator, |
| 6623 | 6650 | tid: Zcu.PerThread.Id, |
| 6624 | 6651 | key: Key, |
| 6652 | ) Allocator.Error!GetOrPutKey { |
| 6653 | return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, key, 0); |
| 6654 | } |
| 6655 | fn getOrPutKeyEnsuringAdditionalCapacity( |
| 6656 | ip: *InternPool, |
| 6657 | gpa: Allocator, |
| 6658 | tid: Zcu.PerThread.Id, |
| 6659 | key: Key, |
| 6660 | additional_capacity: u32, |
| 6625 | 6661 | ) Allocator.Error!GetOrPutKey { |
| 6626 | 6662 | const full_hash = key.hash64(ip); |
| 6627 | 6663 | const hash: u32 = @truncate(full_hash >> 32); |
| ... | ... | @@ -6657,11 +6693,16 @@ fn getOrPutKey( |
| 6657 | 6693 | } |
| 6658 | 6694 | } |
| 6659 | 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 | 6698 | const arena_state = &ip.getLocal(tid).mutate.arena; |
| 6662 | 6699 | var arena = arena_state.promote(gpa); |
| 6663 | 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 | 6706 | const new_map_buf = try arena.allocator().alignedAlloc( |
| 6666 | 6707 | u8, |
| 6667 | 6708 | Map.alignment, |
| ... | ... | @@ -6730,10 +6771,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6730 | 6771 | assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child); |
| 6731 | 6772 | |
| 6732 | 6773 | if (ptr_type.flags.size == .Slice) { |
| 6774 | gop.cancel(); |
| 6733 | 6775 | var new_key = key; |
| 6734 | 6776 | new_key.ptr_type.flags.size = .Many; |
| 6735 | 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); |
| 6737 | 6779 | |
| 6738 | 6780 | try items.ensureUnusedCapacity(1); |
| 6739 | 6781 | items.appendAssumeCapacity(.{ |
| ... | ... | @@ -6913,9 +6955,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6913 | 6955 | }, |
| 6914 | 6956 | .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: { |
| 6915 | 6957 | if (ptr.ty != anon_decl.orig_ty) { |
| 6958 | gop.cancel(); |
| 6916 | 6959 | var new_key = key; |
| 6917 | 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 | 6962 | if (gop == .existing) return gop.existing; |
| 6920 | 6963 | } |
| 6921 | 6964 | break :item .{ |
| ... | ... | @@ -6986,11 +7029,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6986 | 7029 | }, |
| 6987 | 7030 | else => unreachable, |
| 6988 | 7031 | } |
| 7032 | gop.cancel(); |
| 6989 | 7033 | const index_index = try ip.get(gpa, tid, .{ .int = .{ |
| 6990 | 7034 | .ty = .usize_type, |
| 6991 | 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 | 7038 | try items.ensureUnusedCapacity(1); |
| 6995 | 7039 | items.appendAssumeCapacity(.{ |
| 6996 | 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 | 7443 | } |
| 7400 | 7444 | const elem = switch (aggregate.storage) { |
| 7401 | 7445 | .bytes => |bytes| elem: { |
| 7446 | gop.cancel(); |
| 7402 | 7447 | const elem = try ip.get(gpa, tid, .{ .int = .{ |
| 7403 | 7448 | .ty = .u8_type, |
| 7404 | 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 | 7452 | try items.ensureUnusedCapacity(1); |
| 7408 | 7453 | break :elem elem; |
| 7409 | 7454 | }, |
| ... | ... | @@ -8221,9 +8266,9 @@ pub fn getFuncDeclIes( |
| 8221 | 8266 | extra.mutate.len = prev_extra_len; |
| 8222 | 8267 | } |
| 8223 | 8268 | |
| 8224 | | var func_gop = try ip.getOrPutKey(gpa, tid, .{ |
| 8269 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ |
| 8225 | 8270 | .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index), |
| 8226 | | }); |
| 8271 | }, 3); |
| 8227 | 8272 | defer func_gop.deinit(); |
| 8228 | 8273 | if (func_gop == .existing) { |
| 8229 | 8274 | // An existing function type was found; undo the additions to our two arrays. |
| ... | ... | @@ -8231,23 +8276,28 @@ pub fn getFuncDeclIes( |
| 8231 | 8276 | extra.mutate.len = prev_extra_len; |
| 8232 | 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 | 8281 | .error_set_type = error_set_type, |
| 8236 | 8282 | .payload_type = key.bare_return_type, |
| 8237 | | } }); |
| 8283 | } }, 2); |
| 8238 | 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 | 8287 | .inferred_error_set_type = func_index, |
| 8241 | | }); |
| 8288 | }, 1); |
| 8242 | 8289 | defer error_set_type_gop.deinit(); |
| 8290 | error_set_type_gop.putTentative(error_set_type); |
| 8243 | 8291 | var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{ |
| 8244 | 8292 | .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), |
| 8245 | 8293 | }); |
| 8246 | 8294 | defer func_ty_gop.deinit(); |
| 8247 | | assert(func_gop.putAt(3) == func_index); |
| 8248 | | assert(error_union_type_gop.putAt(2) == error_union_type); |
| 8249 | | assert(error_set_type_gop.putAt(1) == error_set_type); |
| 8250 | | assert(func_ty_gop.putAt(0) == func_ty); |
| 8295 | func_ty_gop.putTentative(func_ty); |
| 8296 | |
| 8297 | func_gop.putFinal(func_index); |
| 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 | 8301 | return func_index; |
| 8252 | 8302 | } |
| 8253 | 8303 | |
| ... | ... | @@ -8506,9 +8556,9 @@ pub fn getFuncInstanceIes( |
| 8506 | 8556 | extra.mutate.len = prev_extra_len; |
| 8507 | 8557 | } |
| 8508 | 8558 | |
| 8509 | | var func_gop = try ip.getOrPutKey(gpa, tid, .{ |
| 8559 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ |
| 8510 | 8560 | .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index), |
| 8511 | | }); |
| 8561 | }, 3); |
| 8512 | 8562 | defer func_gop.deinit(); |
| 8513 | 8563 | if (func_gop == .existing) { |
| 8514 | 8564 | // Hot path: undo the additions to our two arrays. |
| ... | ... | @@ -8516,19 +8566,23 @@ pub fn getFuncInstanceIes( |
| 8516 | 8566 | extra.mutate.len = prev_extra_len; |
| 8517 | 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 | 8571 | .error_set_type = error_set_type, |
| 8521 | 8572 | .payload_type = arg.bare_return_type, |
| 8522 | | } }); |
| 8573 | } }, 2); |
| 8523 | 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 | 8577 | .inferred_error_set_type = func_index, |
| 8526 | | }); |
| 8578 | }, 1); |
| 8527 | 8579 | defer error_set_type_gop.deinit(); |
| 8580 | error_set_type_gop.putTentative(error_set_type); |
| 8528 | 8581 | var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{ |
| 8529 | 8582 | .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), |
| 8530 | 8583 | }); |
| 8531 | 8584 | defer func_ty_gop.deinit(); |
| 8585 | func_ty_gop.putTentative(func_ty); |
| 8532 | 8586 | try finishFuncInstance( |
| 8533 | 8587 | ip, |
| 8534 | 8588 | gpa, |
| ... | ... | @@ -8540,10 +8594,11 @@ pub fn getFuncInstanceIes( |
| 8540 | 8594 | arg.alignment, |
| 8541 | 8595 | arg.section, |
| 8542 | 8596 | ); |
| 8543 | | assert(func_gop.putAt(3) == func_index); |
| 8544 | | assert(error_union_type_gop.putAt(2) == error_union_type); |
| 8545 | | assert(error_set_type_gop.putAt(1) == error_set_type); |
| 8546 | | assert(func_ty_gop.putAt(0) == func_ty); |
| 8597 | |
| 8598 | func_gop.putFinal(func_index); |
| 8599 | error_union_type_gop.putFinal(error_union_type); |
| 8600 | error_set_type_gop.putFinal(error_set_type); |
| 8601 | func_ty_gop.putFinal(func_ty); |
| 8547 | 8602 | return func_index; |
| 8548 | 8603 | } |
| 8549 | 8604 | |
| ... | ... | @@ -10839,19 +10894,18 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) OptionalDeclIndex { |
| 10839 | 10894 | while (true) { |
| 10840 | 10895 | const unwrapped_base = base.unwrap(ip); |
| 10841 | 10896 | const base_item = unwrapped_base.getItem(ip); |
| 10842 | | const base_extra_items = unwrapped_base.getExtra(ip).view().items(.@"0"); |
| 10843 | 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 | 10899 | base_item.data + std.meta.fieldIndex(PtrDecl, "decl").? |
| 10846 | 10900 | ]), |
| 10847 | 10901 | inline .ptr_eu_payload, |
| 10848 | 10902 | .ptr_opt_payload, |
| 10849 | 10903 | .ptr_elem, |
| 10850 | 10904 | .ptr_field, |
| 10851 | | => |tag| base = @enumFromInt(base_extra_items[ |
| 10905 | => |tag| base = @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[ |
| 10852 | 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 | 10909 | base_item.data + std.meta.fieldIndex(PtrSlice, "ptr").? |
| 10856 | 10910 | ]), |
| 10857 | 10911 | else => return .none, |