authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 10:43:51-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 11:20:08-04:00
logf290b54f891a67af456529da0f4f824a1e27b4ef
treedb471701e43acc6f640643fab8ba529162daa69f
parent8f292431b03055e789f75aa98888c0f49520e268

InternPool: make `files` more thread-safe


4 files changed, 61 insertions(+), 52 deletions(-)

src/Compilation.zig+4-4
......@@ -2784,7 +2784,7 @@ const Header = extern struct {
27842784 first_dependency_len: u32,
27852785 dep_entries_len: u32,
27862786 free_dep_entries_len: u32,
2787 files_len: u32,
2787 //files_len: u32,
27882788 },
27892789};
27902790
......@@ -2813,7 +2813,7 @@ pub fn saveState(comp: *Compilation) !void {
28132813 .first_dependency_len = @intCast(ip.first_dependency.count()),
28142814 .dep_entries_len = @intCast(ip.dep_entries.items.len),
28152815 .free_dep_entries_len = @intCast(ip.free_dep_entries.items.len),
2816 .files_len = @intCast(ip.files.entries.len),
2816 //.files_len = @intCast(ip.files.entries.len),
28172817 },
28182818 };
28192819 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
......@@ -2838,8 +2838,8 @@ pub fn saveState(comp: *Compilation) !void {
28382838 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.dep_entries.items));
28392839 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.free_dep_entries.items));
28402840
2841 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.keys()));
2842 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.values()));
2841 //addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.keys()));
2842 //addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.values()));
28432843
28442844 // TODO: compilation errors
28452845 // TODO: namespaces
src/InternPool.zig+24-23
......@@ -59,17 +59,6 @@ dep_entries: std.ArrayListUnmanaged(DepEntry) = .{},
5959/// garbage collection pass.
6060free_dep_entries: std.ArrayListUnmanaged(DepEntry.Index) = .{},
6161
62/// Elements are ordered identically to the `import_table` field of `Zcu`.
63///
64/// Unlike `import_table`, this data is serialized as part of incremental
65/// compilation state.
66///
67/// Key is the hash of the path to this file, used to store
68/// `InternPool.TrackedInst`.
69///
70/// Value is the `Decl` of the struct that represents this `File`.
71files: std.AutoArrayHashMapUnmanaged(Cache.BinDigest, OptionalDeclIndex) = .{},
72
7362/// Whether a multi-threaded intern pool is useful.
7463/// Currently `false` until the intern pool is actually accessed
7564/// from multiple threads to reduce the cost of this data structure.
......@@ -346,7 +335,7 @@ const Local = struct {
346335 extra: Extra,
347336 limbs: Limbs,
348337 strings: Strings,
349 files: Files,
338 files: List(File),
350339
351340 decls: Decls,
352341 namespaces: Namespaces,
......@@ -367,7 +356,6 @@ const Local = struct {
367356 else => @compileError("unsupported host"),
368357 };
369358 const Strings = List(struct { u8 });
370 const Files = List(struct { *Zcu.File });
371359
372360 const decls_bucket_width = 8;
373361 const decls_bucket_mask = (1 << decls_bucket_width) - 1;
......@@ -600,7 +588,7 @@ const Local = struct {
600588 const View = std.MultiArrayList(Elem);
601589
602590 /// Must be called when accessing from another thread.
603 fn acquire(list: *const ListSelf) ListSelf {
591 pub fn acquire(list: *const ListSelf) ListSelf {
604592 return .{ .bytes = @atomicLoad([*]align(@alignOf(Elem)) u8, &list.bytes, .acquire) };
605593 }
606594 fn release(list: *ListSelf, new_list: ListSelf) void {
......@@ -614,7 +602,7 @@ const Local = struct {
614602 return @ptrFromInt(@intFromPtr(list.bytes) - bytes_offset);
615603 }
616604
617 fn view(list: ListSelf) View {
605 pub fn view(list: ListSelf) View {
618606 const capacity = list.header().capacity;
619607 assert(capacity > 0); // optimizes `MultiArrayList.Slice.items`
620608 return .{
......@@ -675,7 +663,16 @@ const Local = struct {
675663 };
676664 }
677665
678 pub fn getMutableFiles(local: *Local, gpa: std.mem.Allocator) Files.Mutable {
666 /// Elements are ordered identically to the `import_table` field of `Zcu`.
667 ///
668 /// Unlike `import_table`, this data is serialized as part of incremental
669 /// compilation state.
670 ///
671 /// Key is the hash of the path to this file, used to store
672 /// `InternPool.TrackedInst`.
673 ///
674 /// Value is the `Decl` of the struct that represents this `File`.
675 pub fn getMutableFiles(local: *Local, gpa: std.mem.Allocator) List(File).Mutable {
679676 return .{
680677 .gpa = gpa,
681678 .arena = &local.mutate.arena,
......@@ -957,7 +954,7 @@ pub const FileIndex = enum(u32) {
957954 unwrapped.index);
958955 }
959956 };
960 fn unwrap(file_index: FileIndex, ip: *const InternPool) Unwrapped {
957 pub fn unwrap(file_index: FileIndex, ip: *const InternPool) Unwrapped {
961958 return .{
962959 .tid = @enumFromInt(@intFromEnum(file_index) >> ip.tid_shift_32 & ip.getTidMask()),
963960 .index = @intFromEnum(file_index) & ip.getIndexMask(u32),
......@@ -965,6 +962,12 @@ pub const FileIndex = enum(u32) {
965962 }
966963};
967964
965const File = struct {
966 bin_digest: Cache.BinDigest,
967 file: *Zcu.File,
968 root_decl: OptionalDeclIndex,
969};
970
968971/// An index into `strings`.
969972pub const String = enum(u32) {
970973 /// An empty string.
......@@ -5237,7 +5240,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
52375240 .extra = Local.Extra.empty,
52385241 .limbs = Local.Limbs.empty,
52395242 .strings = Local.Strings.empty,
5240 .files = Local.Files.empty,
5243 .files = Local.List(File).empty,
52415244
52425245 .decls = Local.Decls.empty,
52435246 .namespaces = Local.Namespaces.empty,
......@@ -5321,8 +5324,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
53215324 ip.dep_entries.deinit(gpa);
53225325 ip.free_dep_entries.deinit(gpa);
53235326
5324 ip.files.deinit(gpa);
5325
53265327 gpa.free(ip.shards);
53275328 for (ip.locals) |*local| {
53285329 const buckets_len = local.mutate.namespaces.buckets_list.len;
......@@ -9790,21 +9791,21 @@ pub fn destroyNamespace(
97909791pub fn filePtr(ip: *InternPool, file_index: FileIndex) *Zcu.File {
97919792 const file_index_unwrapped = file_index.unwrap(ip);
97929793 const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
9793 return files.view().items(.@"0")[file_index_unwrapped.index];
9794 return files.view().items(.file)[file_index_unwrapped.index];
97949795}
97959796
97969797pub fn createFile(
97979798 ip: *InternPool,
97989799 gpa: Allocator,
97999800 tid: Zcu.PerThread.Id,
9800 file: *Zcu.File,
9801 file: File,
98019802) Allocator.Error!FileIndex {
98029803 const files = ip.getLocal(tid).getMutableFiles(gpa);
98039804 const file_index_unwrapped: FileIndex.Unwrapped = .{
98049805 .tid = tid,
98059806 .index = files.mutate.len,
98069807 };
9807 try files.append(.{file});
9808 try files.append(file);
98089809 return file_index_unwrapped.wrap(ip);
98099810}
98109811
src/Zcu.zig+15-11
......@@ -2406,8 +2406,7 @@ pub fn deinit(zcu: *Zcu) void {
24062406 for (zcu.import_table.keys()) |key| {
24072407 gpa.free(key);
24082408 }
2409 for (0..zcu.import_table.entries.len) |file_index_usize| {
2410 const file_index: File.Index = @enumFromInt(file_index_usize);
2409 for (zcu.import_table.values()) |file_index| {
24112410 pt.destroyFile(file_index);
24122411 }
24132412 zcu.import_table.deinit(gpa);
......@@ -3537,23 +3536,28 @@ pub fn resolveReferences(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, Resolved
35373536 return result;
35383537}
35393538
3540pub fn fileByIndex(zcu: *Zcu, i: File.Index) *File {
3541 const ip = &zcu.intern_pool;
3542 return ip.filePtr(i);
3539pub fn fileByIndex(zcu: *Zcu, file_index: File.Index) *File {
3540 return zcu.intern_pool.filePtr(file_index);
35433541}
35443542
35453543/// Returns the `Decl` of the struct that represents this `File`.
3546pub fn fileRootDecl(zcu: *const Zcu, i: File.Index) Decl.OptionalIndex {
3544pub fn fileRootDecl(zcu: *const Zcu, file_index: File.Index) Decl.OptionalIndex {
35473545 const ip = &zcu.intern_pool;
3548 return ip.files.values()[@intFromEnum(i)];
3546 const file_index_unwrapped = file_index.unwrap(ip);
3547 const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
3548 return files.view().items(.root_decl)[file_index_unwrapped.index];
35493549}
35503550
3551pub fn setFileRootDecl(zcu: *Zcu, i: File.Index, root_decl: Decl.OptionalIndex) void {
3551pub fn setFileRootDecl(zcu: *Zcu, file_index: File.Index, root_decl: Decl.OptionalIndex) void {
35523552 const ip = &zcu.intern_pool;
3553 ip.files.values()[@intFromEnum(i)] = root_decl;
3553 const file_index_unwrapped = file_index.unwrap(ip);
3554 const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
3555 files.view().items(.root_decl)[file_index_unwrapped.index] = root_decl;
35543556}
35553557
3556pub fn filePathDigest(zcu: *const Zcu, i: File.Index) Cache.BinDigest {
3558pub fn filePathDigest(zcu: *const Zcu, file_index: File.Index) Cache.BinDigest {
35573559 const ip = &zcu.intern_pool;
3558 return ip.files.keys()[@intFromEnum(i)];
3560 const file_index_unwrapped = file_index.unwrap(ip);
3561 const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
3562 return files.view().items(.bin_digest)[file_index_unwrapped.index];
35593563}
src/Zcu/PerThread.zig+18-14
......@@ -1386,15 +1386,16 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
13861386 }
13871387
13881388 const ip = &zcu.intern_pool;
1389 try ip.files.ensureUnusedCapacity(gpa, 1);
1390
13911389 if (mod.builtin_file) |builtin_file| {
1392 const file_index = try ip.createFile(gpa, pt.tid, builtin_file);
1390 const path_digest = Zcu.computePathDigest(zcu, mod, builtin_file.sub_file_path);
1391 const file_index = try ip.createFile(gpa, pt.tid, .{
1392 .bin_digest = path_digest,
1393 .file = builtin_file,
1394 .root_decl = .none,
1395 });
13931396 keep_resolved_path = true; // It's now owned by import_table.
13941397 gop.value_ptr.* = file_index;
13951398 try builtin_file.addReference(zcu, .{ .root = mod });
1396 const path_digest = Zcu.computePathDigest(zcu, mod, builtin_file.sub_file_path);
1397 ip.files.putAssumeCapacityNoClobber(path_digest, .none);
13981399 return .{
13991400 .file = builtin_file,
14001401 .file_index = file_index,
......@@ -1409,7 +1410,12 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
14091410 const new_file = try gpa.create(Zcu.File);
14101411 errdefer gpa.destroy(new_file);
14111412
1412 const new_file_index = try ip.createFile(gpa, pt.tid, new_file);
1413 const path_digest = zcu.computePathDigest(mod, sub_file_path);
1414 const new_file_index = try ip.createFile(gpa, pt.tid, .{
1415 .bin_digest = path_digest,
1416 .file = new_file,
1417 .root_decl = .none,
1418 });
14131419 keep_resolved_path = true; // It's now owned by import_table.
14141420 gop.value_ptr.* = new_file_index;
14151421 new_file.* = .{
......@@ -1425,10 +1431,7 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
14251431 .mod = mod,
14261432 };
14271433
1428 const path_digest = zcu.computePathDigest(mod, sub_file_path);
1429
14301434 try new_file.addReference(zcu, .{ .root = mod });
1431 ip.files.putAssumeCapacityNoClobber(path_digest, .none);
14321435 return .{
14331436 .file = new_file,
14341437 .file_index = new_file_index,
......@@ -1489,8 +1492,6 @@ pub fn importFile(
14891492
14901493 const ip = &zcu.intern_pool;
14911494
1492 try ip.files.ensureUnusedCapacity(gpa, 1);
1493
14941495 const new_file = try gpa.create(Zcu.File);
14951496 errdefer gpa.destroy(new_file);
14961497
......@@ -1515,7 +1516,12 @@ pub fn importFile(
15151516 resolved_root_path, resolved_path, sub_file_path, import_string,
15161517 });
15171518
1518 const new_file_index = try ip.createFile(gpa, pt.tid, new_file);
1519 const path_digest = zcu.computePathDigest(mod, sub_file_path);
1520 const new_file_index = try ip.createFile(gpa, pt.tid, .{
1521 .bin_digest = path_digest,
1522 .file = new_file,
1523 .root_decl = .none,
1524 });
15191525 keep_resolved_path = true; // It's now owned by import_table.
15201526 gop.value_ptr.* = new_file_index;
15211527 new_file.* = .{
......@@ -1531,8 +1537,6 @@ pub fn importFile(
15311537 .mod = mod,
15321538 };
15331539
1534 const path_digest = zcu.computePathDigest(mod, sub_file_path);
1535 ip.files.putAssumeCapacityNoClobber(path_digest, .none);
15361540 return .{
15371541 .file = new_file,
15381542 .file_index = new_file_index,