authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-16 00:43:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:20-07:00
logb6dd5ad3578c69ad4a4b596477ccb86f087a99e6
tree50ad38ef58f91395d0941e0b30da543dea40a755
parent2047a6b82d2e6cdbddde3e7f1c93df9e72216052

MachO: rip out the caching mechanism

This is redundant with CacheMode.whole which caches everything, including linking output. Linker code does not need to concern itself with caching like this.

1 files changed, 24 insertions(+), 100 deletions(-)

src/link/MachO.zig+24-100
......@@ -74,12 +74,6 @@ stub_table_count_dirty: bool = false,
7474stub_table_contents_dirty: bool = false,
7575stub_helper_preamble_allocated: bool = false,
7676
77/// A helper var to indicate if we are at the start of the incremental updates, or
78/// already somewhere further along the update-and-run chain.
79/// TODO once we add opening a prelinked output binary from file, this will become
80/// obsolete as we will carry on where we left off.
81cold_start: bool = true,
82
8377/// List of atoms that are either synthetic or map directly to the Zig source program.
8478atoms: std.ArrayListUnmanaged(Atom) = .{},
8579
......@@ -404,91 +398,38 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
404398 var libs = std.StringArrayHashMap(link.SystemLib).init(arena);
405399 try self.resolveLibSystem(arena, comp, &libs);
406400
407 const id_symlink_basename = "link.id";
408
409 const cache_dir_handle = module.zig_cache_artifact_directory.handle;
410 var man: Cache.Manifest = undefined;
411 defer man.deinit();
412
413 var digest: [Cache.hex_digest_len]u8 = undefined;
414 man = comp.cache_parent.obtain();
415 man.want_shared_lock = false;
416401 self.base.releaseLock();
417402
418 man.hash.addListOfBytes(libs.keys());
419
420 _ = try man.hit();
421 digest = man.final();
422
423 var prev_digest_buf: [digest.len]u8 = undefined;
424 const prev_digest: []u8 = Cache.readSmallFile(
425 cache_dir_handle,
426 id_symlink_basename,
427 &prev_digest_buf,
428 ) catch |err| blk: {
429 log.debug("MachO Zld new_digest={s} error: {s}", .{
430 std.fmt.fmtSliceHexLower(&digest),
431 @errorName(err),
432 });
433 // Handle this as a cache miss.
434 break :blk prev_digest_buf[0..0];
435 };
436 const cache_miss: bool = cache_miss: {
437 if (mem.eql(u8, prev_digest, &digest)) {
438 log.debug("MachO Zld digest={s} match", .{
439 std.fmt.fmtSliceHexLower(&digest),
440 });
441 if (!self.cold_start) {
442 log.debug(" skipping parsing linker line objects", .{});
443 break :cache_miss false;
444 } else {
445 log.debug(" TODO parse prelinked binary and continue linking where we left off", .{});
446 }
447 }
448 log.debug("MachO Zld prev_digest={s} new_digest={s}", .{
449 std.fmt.fmtSliceHexLower(prev_digest),
450 std.fmt.fmtSliceHexLower(&digest),
451 });
452 // We are about to change the output file to be different, so we invalidate the build hash now.
453 cache_dir_handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
454 error.FileNotFound => {},
455 else => |e| return e,
456 };
457 break :cache_miss true;
458 };
459
460 if (cache_miss) {
461 for (self.dylibs.items) |*dylib| {
462 dylib.deinit(gpa);
463 }
464 self.dylibs.clearRetainingCapacity();
465 self.dylibs_map.clearRetainingCapacity();
466 self.referenced_dylibs.clearRetainingCapacity();
467
468 var dependent_libs = std.fifo.LinearFifo(DylibReExportInfo, .Dynamic).init(arena);
403 for (self.dylibs.items) |*dylib| {
404 dylib.deinit(gpa);
405 }
406 self.dylibs.clearRetainingCapacity();
407 self.dylibs_map.clearRetainingCapacity();
408 self.referenced_dylibs.clearRetainingCapacity();
469409
470 for (libs.keys(), libs.values()) |path, lib| {
471 const in_file = try std.fs.cwd().openFile(path, .{});
472 defer in_file.close();
410 var dependent_libs = std.fifo.LinearFifo(DylibReExportInfo, .Dynamic).init(arena);
473411
474 var parse_ctx = ParseErrorCtx.init(gpa);
475 defer parse_ctx.deinit();
412 for (libs.keys(), libs.values()) |path, lib| {
413 const in_file = try std.fs.cwd().openFile(path, .{});
414 defer in_file.close();
476415
477 self.parseLibrary(
478 in_file,
479 path,
480 lib,
481 false,
482 false,
483 null,
484 &dependent_libs,
485 &parse_ctx,
486 ) catch |err| try self.handleAndReportParseError(path, err, &parse_ctx);
487 }
416 var parse_ctx = ParseErrorCtx.init(gpa);
417 defer parse_ctx.deinit();
488418
489 try self.parseDependentLibs(&dependent_libs);
419 self.parseLibrary(
420 in_file,
421 path,
422 lib,
423 false,
424 false,
425 null,
426 &dependent_libs,
427 &parse_ctx,
428 ) catch |err| try self.handleAndReportParseError(path, err, &parse_ctx);
490429 }
491430
431 try self.parseDependentLibs(&dependent_libs);
432
492433 try self.resolveSymbols();
493434
494435 if (self.getEntryPoint() == null) {
......@@ -666,23 +607,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
666607 // Flush debug symbols bundle.
667608 try d_sym.flushModule(self);
668609 }
669
670 if (cache_miss) {
671 // Update the file with the digest. If it fails we can continue; it only
672 // means that the next invocation will have an unnecessary cache miss.
673 Cache.writeSmallFile(cache_dir_handle, id_symlink_basename, &digest) catch |err| {
674 log.debug("failed to save linking hash digest file: {s}", .{@errorName(err)});
675 };
676 // Again failure here only means an unnecessary cache miss.
677 man.writeManifest() catch |err| {
678 log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)});
679 };
680 // We hang on to this lock so that the output file path can be used without
681 // other processes clobbering it.
682 self.base.lock = man.toOwnedLock();
683 }
684
685 self.cold_start = false;
686610}
687611
688612/// XNU starting with Big Sur running on arm64 is caching inodes of running binaries.