authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-06 03:48:32-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-07 22:59:52-04:00
log49b25475ad0d224e13d989f9ff860b32fca6315a
treeeb081528906b486ada087636bd72bbf42def8911
parent383cffbfae2d6be5862cbadaf138618c5b37b345

InternPool: remove usage of data with simple indices

This allows them to be atomically replaced.

1 files changed, 74 insertions(+), 79 deletions(-)

src/InternPool.zig+74-79
......@@ -816,7 +816,7 @@ pub const String = enum(u32) {
816816 };
817817 }
818818
819 noinline fn toOverlongSlice(string: String, ip: *const InternPool) []const u8 {
819 fn toOverlongSlice(string: String, ip: *const InternPool) []const u8 {
820820 const unwrapped = string.unwrap(ip);
821821 return ip.getLocalShared(unwrapped.tid).strings.acquire().view().items(.@"0")[unwrapped.index..];
822822 }
......@@ -3237,18 +3237,18 @@ pub const Index = enum(u32) {
32373237 }
32383238 };
32393239
3240 pub inline fn getItem(index: Index, ip: *const InternPool) Item {
3240 pub fn getItem(index: Index, ip: *const InternPool) Item {
32413241 const item_ptr = index.itemPtr(ip);
32423242 const tag = @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);
32433243 return .{ .tag = tag, .data = item_ptr.data_ptr.* };
32443244 }
32453245
3246 pub inline fn getTag(index: Index, ip: *const InternPool) Tag {
3246 pub fn getTag(index: Index, ip: *const InternPool) Tag {
32473247 const item_ptr = index.itemPtr(ip);
32483248 return @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);
32493249 }
32503250
3251 pub inline fn getData(index: Index, ip: *const InternPool) u32 {
3251 pub fn getData(index: Index, ip: *const InternPool) u32 {
32523252 return index.getItem(ip).data;
32533253 }
32543254
......@@ -3340,7 +3340,7 @@ pub const Index = enum(u32) {
33403340 },
33413341 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
33423342 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
3343 simple_type: struct { data: SimpleType },
3343 simple_type: void,
33443344 type_opaque: struct { data: *Tag.TypeOpaque },
33453345 type_struct: struct { data: *Tag.TypeStruct },
33463346 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
......@@ -3360,7 +3360,7 @@ pub const Index = enum(u32) {
33603360 },
33613361
33623362 undef: DataIsIndex,
3363 simple_value: struct { data: SimpleValue },
3363 simple_value: void,
33643364 ptr_decl: struct { data: *PtrDecl },
33653365 ptr_comptime_alloc: struct { data: *PtrComptimeAlloc },
33663366 ptr_anon_decl: struct { data: *PtrAnonDecl },
......@@ -4386,64 +4386,64 @@ pub const TypeStructAnon = struct {
43864386/// implement logic that only wants to deal with types because the logic can
43874387/// ignore all simple values. Note that technically, types are values.
43884388pub const SimpleType = enum(u32) {
4389 f16,
4390 f32,
4391 f64,
4392 f80,
4393 f128,
4394 usize,
4395 isize,
4396 c_char,
4397 c_short,
4398 c_ushort,
4399 c_int,
4400 c_uint,
4401 c_long,
4402 c_ulong,
4403 c_longlong,
4404 c_ulonglong,
4405 c_longdouble,
4406 anyopaque,
4407 bool,
4408 void,
4409 type,
4410 anyerror,
4411 comptime_int,
4412 comptime_float,
4413 noreturn,
4414 null,
4415 undefined,
4416 enum_literal,
4417
4418 atomic_order,
4419 atomic_rmw_op,
4420 calling_convention,
4421 address_space,
4422 float_mode,
4423 reduce_op,
4424 call_modifier,
4425 prefetch_options,
4426 export_options,
4427 extern_options,
4428 type_info,
4429
4430 adhoc_inferred_error_set,
4431 generic_poison,
4389 f16 = @intFromEnum(Index.f16_type),
4390 f32 = @intFromEnum(Index.f32_type),
4391 f64 = @intFromEnum(Index.f64_type),
4392 f80 = @intFromEnum(Index.f80_type),
4393 f128 = @intFromEnum(Index.f128_type),
4394 usize = @intFromEnum(Index.usize_type),
4395 isize = @intFromEnum(Index.isize_type),
4396 c_char = @intFromEnum(Index.c_char_type),
4397 c_short = @intFromEnum(Index.c_short_type),
4398 c_ushort = @intFromEnum(Index.c_ushort_type),
4399 c_int = @intFromEnum(Index.c_int_type),
4400 c_uint = @intFromEnum(Index.c_uint_type),
4401 c_long = @intFromEnum(Index.c_long_type),
4402 c_ulong = @intFromEnum(Index.c_ulong_type),
4403 c_longlong = @intFromEnum(Index.c_longlong_type),
4404 c_ulonglong = @intFromEnum(Index.c_ulonglong_type),
4405 c_longdouble = @intFromEnum(Index.c_longdouble_type),
4406 anyopaque = @intFromEnum(Index.anyopaque_type),
4407 bool = @intFromEnum(Index.bool_type),
4408 void = @intFromEnum(Index.void_type),
4409 type = @intFromEnum(Index.type_type),
4410 anyerror = @intFromEnum(Index.anyerror_type),
4411 comptime_int = @intFromEnum(Index.comptime_int_type),
4412 comptime_float = @intFromEnum(Index.comptime_float_type),
4413 noreturn = @intFromEnum(Index.noreturn_type),
4414 null = @intFromEnum(Index.null_type),
4415 undefined = @intFromEnum(Index.undefined_type),
4416 enum_literal = @intFromEnum(Index.enum_literal_type),
4417
4418 atomic_order = @intFromEnum(Index.atomic_order_type),
4419 atomic_rmw_op = @intFromEnum(Index.atomic_rmw_op_type),
4420 calling_convention = @intFromEnum(Index.calling_convention_type),
4421 address_space = @intFromEnum(Index.address_space_type),
4422 float_mode = @intFromEnum(Index.float_mode_type),
4423 reduce_op = @intFromEnum(Index.reduce_op_type),
4424 call_modifier = @intFromEnum(Index.call_modifier_type),
4425 prefetch_options = @intFromEnum(Index.prefetch_options_type),
4426 export_options = @intFromEnum(Index.export_options_type),
4427 extern_options = @intFromEnum(Index.extern_options_type),
4428 type_info = @intFromEnum(Index.type_info_type),
4429
4430 adhoc_inferred_error_set = @intFromEnum(Index.adhoc_inferred_error_set_type),
4431 generic_poison = @intFromEnum(Index.generic_poison_type),
44324432};
44334433
44344434pub const SimpleValue = enum(u32) {
44354435 /// This is untyped `undefined`.
4436 undefined,
4437 void,
4436 undefined = @intFromEnum(Index.undef),
4437 void = @intFromEnum(Index.void_value),
44384438 /// This is untyped `null`.
4439 null,
4439 null = @intFromEnum(Index.null_value),
44404440 /// This is the untyped empty struct literal: `.{}`
4441 empty_struct,
4442 true,
4443 false,
4444 @"unreachable",
4441 empty_struct = @intFromEnum(Index.empty_struct),
4442 true = @intFromEnum(Index.bool_true),
4443 false = @intFromEnum(Index.bool_false),
4444 @"unreachable" = @intFromEnum(Index.unreachable_value),
44454445
4446 generic_poison,
4446 generic_poison = @intFromEnum(Index.generic_poison),
44474447};
44484448
44494449/// Stored as a power-of-two, with one special value to indicate none.
......@@ -5063,8 +5063,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
50635063 .sentinel = .none,
50645064 } };
50655065 },
5066 .simple_type => .{ .simple_type = @enumFromInt(data) },
5067 .simple_value => .{ .simple_value = @enumFromInt(data) },
5066 .simple_type => .{ .simple_type = @enumFromInt(@intFromEnum(index)) },
5067 .simple_value => .{ .simple_value = @enumFromInt(@intFromEnum(index)) },
50685068
50695069 .type_vector => {
50705070 const vector_info = ip.extraData(Vector, data);
......@@ -5914,15 +5914,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
59145914 });
59155915 },
59165916 .simple_type => |simple_type| {
5917 assert(@intFromEnum(simple_type) == items.lenPtr().*);
59175918 items.appendAssumeCapacity(.{
59185919 .tag = .simple_type,
5919 .data = @intFromEnum(simple_type),
5920 .data = 0, // avoid writing `undefined` bits to a file
59205921 });
59215922 },
59225923 .simple_value => |simple_value| {
5924 assert(@intFromEnum(simple_value) == items.lenPtr().*);
59235925 items.appendAssumeCapacity(.{
59245926 .tag = .simple_value,
5925 .data = @intFromEnum(simple_value),
5927 .data = 0, // avoid writing `undefined` bits to a file
59265928 });
59275929 },
59285930 .undef => |ty| {
......@@ -8092,22 +8094,16 @@ fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex
80928094pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
80938095 const unwrapped = index.unwrap(ip);
80948096 if (@intFromEnum(index) < static_keys.len) {
8095 if (tid != .main or unwrapped.tid != .main) @panic("This operation is impossible to be thread-safe");
80968097 // The item being removed replaced a special index via `InternPool.resolveBuiltinType`.
80978098 // Restore the original item at this index.
8098 var items = ip.getLocalShared(unwrapped.tid).items.view();
8099 switch (static_keys[@intFromEnum(index)]) {
8100 .simple_type => |s| items.set(@intFromEnum(index), .{
8101 .tag = .simple_type,
8102 .data = @intFromEnum(s),
8103 }),
8104 else => unreachable,
8105 }
8099 assert(static_keys[@intFromEnum(index)] == .simple_type);
8100 const items = ip.getLocalShared(unwrapped.tid).items.view();
8101 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], .simple_type, .monotonic);
81068102 return;
81078103 }
81088104
81098105 if (unwrapped.tid == tid) {
8110 const items_len = &ip.getLocal(tid).mutate.items.len;
8106 const items_len = &ip.getLocal(unwrapped.tid).mutate.items.len;
81118107 if (unwrapped.index == items_len.* - 1) {
81128108 // Happy case - we can just drop the item without affecting any other indices.
81138109 items_len.* -= 1;
......@@ -8119,7 +8115,7 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
81198115 // Thus, we will rewrite the tag to `removed`, leaking the item until
81208116 // next GC but causing `KeyAdapter` to ignore it.
81218117 const items = ip.getLocalShared(unwrapped.tid).items.view();
8122 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], .removed, .release);
8118 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], .removed, .monotonic);
81238119}
81248120
81258121fn addInt(
......@@ -9697,7 +9693,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
96979693 .type_enum_auto,
96989694 .type_enum_explicit,
96999695 .type_enum_nonexhaustive,
9700 .simple_type,
97019696 .type_opaque,
97029697 .type_struct,
97039698 .type_struct_anon,
......@@ -9713,7 +9708,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
97139708 .only_possible_value,
97149709 => @enumFromInt(index.getData(ip)),
97159710
9716 .simple_value => unreachable, // handled via Index above
9711 .simple_type, .simple_value => unreachable, // handled via Index above
97179712
97189713 inline .ptr_decl,
97199714 .ptr_comptime_alloc,
......@@ -10246,11 +10241,11 @@ pub fn resolveBuiltinType(
1024610241 (ip.zigTypeTagOrPoison(resolved_index) catch unreachable));
1024710242
1024810243 // Copy the data
10249 const resolved_item = resolved_index.getItem(ip);
10250 const want_unwrapped = want_index.unwrap(ip);
10251 if (tid != .main or want_unwrapped.tid != .main) @panic("This operation is impossible to be thread-safe");
10252 var want_items = ip.getLocalShared(want_unwrapped.tid).items.view();
10253 want_items.set(want_unwrapped.index, resolved_item);
10244 const item = resolved_index.getItem(ip);
10245 const unwrapped = want_index.unwrap(ip);
10246 var items = ip.getLocalShared(unwrapped.tid).items.view().slice();
10247 items.items(.data)[unwrapped.index] = item.data;
10248 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], item.tag, .release);
1025410249 ip.remove(tid, resolved_index);
1025510250}
1025610251