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) {...@@ -816,7 +816,7 @@ pub const String = enum(u32) {
816 };816 };
817 }817 }
818818
819 noinline fn toOverlongSlice(string: String, ip: *const InternPool) []const u8 {819 fn toOverlongSlice(string: String, ip: *const InternPool) []const u8 {
820 const unwrapped = string.unwrap(ip);820 const unwrapped = string.unwrap(ip);
821 return ip.getLocalShared(unwrapped.tid).strings.acquire().view().items(.@"0")[unwrapped.index..];821 return ip.getLocalShared(unwrapped.tid).strings.acquire().view().items(.@"0")[unwrapped.index..];
822 }822 }
...@@ -3237,18 +3237,18 @@ pub const Index = enum(u32) {...@@ -3237,18 +3237,18 @@ pub const Index = enum(u32) {
3237 }3237 }
3238 };3238 };
32393239
3240 pub inline fn getItem(index: Index, ip: *const InternPool) Item {3240 pub fn getItem(index: Index, ip: *const InternPool) Item {
3241 const item_ptr = index.itemPtr(ip);3241 const item_ptr = index.itemPtr(ip);
3242 const tag = @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);3242 const tag = @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);
3243 return .{ .tag = tag, .data = item_ptr.data_ptr.* };3243 return .{ .tag = tag, .data = item_ptr.data_ptr.* };
3244 }3244 }
32453245
3246 pub inline fn getTag(index: Index, ip: *const InternPool) Tag {3246 pub fn getTag(index: Index, ip: *const InternPool) Tag {
3247 const item_ptr = index.itemPtr(ip);3247 const item_ptr = index.itemPtr(ip);
3248 return @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);3248 return @atomicLoad(Tag, item_ptr.tag_ptr, .acquire);
3249 }3249 }
32503250
3251 pub inline fn getData(index: Index, ip: *const InternPool) u32 {3251 pub fn getData(index: Index, ip: *const InternPool) u32 {
3252 return index.getItem(ip).data;3252 return index.getItem(ip).data;
3253 }3253 }
32543254
...@@ -3340,7 +3340,7 @@ pub const Index = enum(u32) {...@@ -3340,7 +3340,7 @@ pub const Index = enum(u32) {
3340 },3340 },
3341 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,3341 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
3342 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,3342 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
3343 simple_type: struct { data: SimpleType },3343 simple_type: void,
3344 type_opaque: struct { data: *Tag.TypeOpaque },3344 type_opaque: struct { data: *Tag.TypeOpaque },
3345 type_struct: struct { data: *Tag.TypeStruct },3345 type_struct: struct { data: *Tag.TypeStruct },
3346 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,3346 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
...@@ -3360,7 +3360,7 @@ pub const Index = enum(u32) {...@@ -3360,7 +3360,7 @@ pub const Index = enum(u32) {
3360 },3360 },
33613361
3362 undef: DataIsIndex,3362 undef: DataIsIndex,
3363 simple_value: struct { data: SimpleValue },3363 simple_value: void,
3364 ptr_decl: struct { data: *PtrDecl },3364 ptr_decl: struct { data: *PtrDecl },
3365 ptr_comptime_alloc: struct { data: *PtrComptimeAlloc },3365 ptr_comptime_alloc: struct { data: *PtrComptimeAlloc },
3366 ptr_anon_decl: struct { data: *PtrAnonDecl },3366 ptr_anon_decl: struct { data: *PtrAnonDecl },
...@@ -4386,64 +4386,64 @@ pub const TypeStructAnon = struct {...@@ -4386,64 +4386,64 @@ pub const TypeStructAnon = struct {
4386/// implement logic that only wants to deal with types because the logic can4386/// implement logic that only wants to deal with types because the logic can
4387/// ignore all simple values. Note that technically, types are values.4387/// ignore all simple values. Note that technically, types are values.
4388pub const SimpleType = enum(u32) {4388pub const SimpleType = enum(u32) {
4389 f16,4389 f16 = @intFromEnum(Index.f16_type),
4390 f32,4390 f32 = @intFromEnum(Index.f32_type),
4391 f64,4391 f64 = @intFromEnum(Index.f64_type),
4392 f80,4392 f80 = @intFromEnum(Index.f80_type),
4393 f128,4393 f128 = @intFromEnum(Index.f128_type),
4394 usize,4394 usize = @intFromEnum(Index.usize_type),
4395 isize,4395 isize = @intFromEnum(Index.isize_type),
4396 c_char,4396 c_char = @intFromEnum(Index.c_char_type),
4397 c_short,4397 c_short = @intFromEnum(Index.c_short_type),
4398 c_ushort,4398 c_ushort = @intFromEnum(Index.c_ushort_type),
4399 c_int,4399 c_int = @intFromEnum(Index.c_int_type),
4400 c_uint,4400 c_uint = @intFromEnum(Index.c_uint_type),
4401 c_long,4401 c_long = @intFromEnum(Index.c_long_type),
4402 c_ulong,4402 c_ulong = @intFromEnum(Index.c_ulong_type),
4403 c_longlong,4403 c_longlong = @intFromEnum(Index.c_longlong_type),
4404 c_ulonglong,4404 c_ulonglong = @intFromEnum(Index.c_ulonglong_type),
4405 c_longdouble,4405 c_longdouble = @intFromEnum(Index.c_longdouble_type),
4406 anyopaque,4406 anyopaque = @intFromEnum(Index.anyopaque_type),
4407 bool,4407 bool = @intFromEnum(Index.bool_type),
4408 void,4408 void = @intFromEnum(Index.void_type),
4409 type,4409 type = @intFromEnum(Index.type_type),
4410 anyerror,4410 anyerror = @intFromEnum(Index.anyerror_type),
4411 comptime_int,4411 comptime_int = @intFromEnum(Index.comptime_int_type),
4412 comptime_float,4412 comptime_float = @intFromEnum(Index.comptime_float_type),
4413 noreturn,4413 noreturn = @intFromEnum(Index.noreturn_type),
4414 null,4414 null = @intFromEnum(Index.null_type),
4415 undefined,4415 undefined = @intFromEnum(Index.undefined_type),
4416 enum_literal,4416 enum_literal = @intFromEnum(Index.enum_literal_type),
44174417
4418 atomic_order,4418 atomic_order = @intFromEnum(Index.atomic_order_type),
4419 atomic_rmw_op,4419 atomic_rmw_op = @intFromEnum(Index.atomic_rmw_op_type),
4420 calling_convention,4420 calling_convention = @intFromEnum(Index.calling_convention_type),
4421 address_space,4421 address_space = @intFromEnum(Index.address_space_type),
4422 float_mode,4422 float_mode = @intFromEnum(Index.float_mode_type),
4423 reduce_op,4423 reduce_op = @intFromEnum(Index.reduce_op_type),
4424 call_modifier,4424 call_modifier = @intFromEnum(Index.call_modifier_type),
4425 prefetch_options,4425 prefetch_options = @intFromEnum(Index.prefetch_options_type),
4426 export_options,4426 export_options = @intFromEnum(Index.export_options_type),
4427 extern_options,4427 extern_options = @intFromEnum(Index.extern_options_type),
4428 type_info,4428 type_info = @intFromEnum(Index.type_info_type),
44294429
4430 adhoc_inferred_error_set,4430 adhoc_inferred_error_set = @intFromEnum(Index.adhoc_inferred_error_set_type),
4431 generic_poison,4431 generic_poison = @intFromEnum(Index.generic_poison_type),
4432};4432};
44334433
4434pub const SimpleValue = enum(u32) {4434pub const SimpleValue = enum(u32) {
4435 /// This is untyped `undefined`.4435 /// This is untyped `undefined`.
4436 undefined,4436 undefined = @intFromEnum(Index.undef),
4437 void,4437 void = @intFromEnum(Index.void_value),
4438 /// This is untyped `null`.4438 /// This is untyped `null`.
4439 null,4439 null = @intFromEnum(Index.null_value),
4440 /// This is the untyped empty struct literal: `.{}`4440 /// This is the untyped empty struct literal: `.{}`
4441 empty_struct,4441 empty_struct = @intFromEnum(Index.empty_struct),
4442 true,4442 true = @intFromEnum(Index.bool_true),
4443 false,4443 false = @intFromEnum(Index.bool_false),
4444 @"unreachable",4444 @"unreachable" = @intFromEnum(Index.unreachable_value),
44454445
4446 generic_poison,4446 generic_poison = @intFromEnum(Index.generic_poison),
4447};4447};
44484448
4449/// Stored as a power-of-two, with one special value to indicate none.4449/// 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 {...@@ -5063,8 +5063,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
5063 .sentinel = .none,5063 .sentinel = .none,
5064 } };5064 } };
5065 },5065 },
5066 .simple_type => .{ .simple_type = @enumFromInt(data) },5066 .simple_type => .{ .simple_type = @enumFromInt(@intFromEnum(index)) },
5067 .simple_value => .{ .simple_value = @enumFromInt(data) },5067 .simple_value => .{ .simple_value = @enumFromInt(@intFromEnum(index)) },
50685068
5069 .type_vector => {5069 .type_vector => {
5070 const vector_info = ip.extraData(Vector, data);5070 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...@@ -5914,15 +5914,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
5914 });5914 });
5915 },5915 },
5916 .simple_type => |simple_type| {5916 .simple_type => |simple_type| {
5917 assert(@intFromEnum(simple_type) == items.lenPtr().*);
5917 items.appendAssumeCapacity(.{5918 items.appendAssumeCapacity(.{
5918 .tag = .simple_type,5919 .tag = .simple_type,
5919 .data = @intFromEnum(simple_type),5920 .data = 0, // avoid writing `undefined` bits to a file
5920 });5921 });
5921 },5922 },
5922 .simple_value => |simple_value| {5923 .simple_value => |simple_value| {
5924 assert(@intFromEnum(simple_value) == items.lenPtr().*);
5923 items.appendAssumeCapacity(.{5925 items.appendAssumeCapacity(.{
5924 .tag = .simple_value,5926 .tag = .simple_value,
5925 .data = @intFromEnum(simple_value),5927 .data = 0, // avoid writing `undefined` bits to a file
5926 });5928 });
5927 },5929 },
5928 .undef => |ty| {5930 .undef => |ty| {
...@@ -8092,22 +8094,16 @@ fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex...@@ -8092,22 +8094,16 @@ fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex
8092pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {8094pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
8093 const unwrapped = index.unwrap(ip);8095 const unwrapped = index.unwrap(ip);
8094 if (@intFromEnum(index) < static_keys.len) {8096 if (@intFromEnum(index) < static_keys.len) {
8095 if (tid != .main or unwrapped.tid != .main) @panic("This operation is impossible to be thread-safe");
8096 // The item being removed replaced a special index via `InternPool.resolveBuiltinType`.8097 // The item being removed replaced a special index via `InternPool.resolveBuiltinType`.
8097 // Restore the original item at this index.8098 // Restore the original item at this index.
8098 var items = ip.getLocalShared(unwrapped.tid).items.view();8099 assert(static_keys[@intFromEnum(index)] == .simple_type);
8099 switch (static_keys[@intFromEnum(index)]) {8100 const items = ip.getLocalShared(unwrapped.tid).items.view();
8100 .simple_type => |s| items.set(@intFromEnum(index), .{8101 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], .simple_type, .monotonic);
8101 .tag = .simple_type,
8102 .data = @intFromEnum(s),
8103 }),
8104 else => unreachable,
8105 }
8106 return;8102 return;
8107 }8103 }
81088104
8109 if (unwrapped.tid == tid) {8105 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;
8111 if (unwrapped.index == items_len.* - 1) {8107 if (unwrapped.index == items_len.* - 1) {
8112 // Happy case - we can just drop the item without affecting any other indices.8108 // Happy case - we can just drop the item without affecting any other indices.
8113 items_len.* -= 1;8109 items_len.* -= 1;
...@@ -8119,7 +8115,7 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {...@@ -8119,7 +8115,7 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
8119 // Thus, we will rewrite the tag to `removed`, leaking the item until8115 // Thus, we will rewrite the tag to `removed`, leaking the item until
8120 // next GC but causing `KeyAdapter` to ignore it.8116 // next GC but causing `KeyAdapter` to ignore it.
8121 const items = ip.getLocalShared(unwrapped.tid).items.view();8117 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);
8123}8119}
81248120
8125fn addInt(8121fn addInt(
...@@ -9697,7 +9693,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -9697,7 +9693,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
9697 .type_enum_auto,9693 .type_enum_auto,
9698 .type_enum_explicit,9694 .type_enum_explicit,
9699 .type_enum_nonexhaustive,9695 .type_enum_nonexhaustive,
9700 .simple_type,
9701 .type_opaque,9696 .type_opaque,
9702 .type_struct,9697 .type_struct,
9703 .type_struct_anon,9698 .type_struct_anon,
...@@ -9713,7 +9708,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -9713,7 +9708,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
9713 .only_possible_value,9708 .only_possible_value,
9714 => @enumFromInt(index.getData(ip)),9709 => @enumFromInt(index.getData(ip)),
97159710
9716 .simple_value => unreachable, // handled via Index above9711 .simple_type, .simple_value => unreachable, // handled via Index above
97179712
9718 inline .ptr_decl,9713 inline .ptr_decl,
9719 .ptr_comptime_alloc,9714 .ptr_comptime_alloc,
...@@ -10246,11 +10241,11 @@ pub fn resolveBuiltinType(...@@ -10246,11 +10241,11 @@ pub fn resolveBuiltinType(
10246 (ip.zigTypeTagOrPoison(resolved_index) catch unreachable));10241 (ip.zigTypeTagOrPoison(resolved_index) catch unreachable));
1024710242
10248 // Copy the data10243 // Copy the data
10249 const resolved_item = resolved_index.getItem(ip);10244 const item = resolved_index.getItem(ip);
10250 const want_unwrapped = want_index.unwrap(ip);10245 const unwrapped = want_index.unwrap(ip);
10251 if (tid != .main or want_unwrapped.tid != .main) @panic("This operation is impossible to be thread-safe");10246 var items = ip.getLocalShared(unwrapped.tid).items.view().slice();
10252 var want_items = ip.getLocalShared(want_unwrapped.tid).items.view();10247 items.items(.data)[unwrapped.index] = item.data;
10253 want_items.set(want_unwrapped.index, resolved_item);10248 @atomicStore(Tag, &items.items(.tag)[unwrapped.index], item.tag, .release);
10254 ip.remove(tid, resolved_index);10249 ip.remove(tid, resolved_index);
10255}10250}
1025610251