| ... | @@ -221,8 +221,13 @@ lazy_bindings: BindingTable = .{}, | ... | @@ -221,8 +221,13 @@ lazy_bindings: BindingTable = .{}, |
| 221 | /// Table of tracked Decls. | 221 | /// Table of tracked Decls. |
| 222 | decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, | 222 | decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, |
| 223 | | 223 | |
| 224 | /// Mach task used when the compiler is in hot-code swapping mode. | 224 | /// Hot-code swapping state. |
| 225 | mach_task: ?std.os.darwin.MachTask = null, | 225 | hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, |
| | 226 | |
| | 227 | const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| | 228 | .macos => true, |
| | 229 | else => false, |
| | 230 | }; |
| 226 | | 231 | |
| 227 | const DeclMetadata = struct { | 232 | const DeclMetadata = struct { |
| 228 | atom: Atom.Index, | 233 | atom: Atom.Index, |
| ... | @@ -303,6 +308,10 @@ pub const SymbolWithLoc = struct { | ... | @@ -303,6 +308,10 @@ pub const SymbolWithLoc = struct { |
| 303 | } | 308 | } |
| 304 | }; | 309 | }; |
| 305 | | 310 | |
| | 311 | const HotUpdateState = struct { |
| | 312 | mach_task: ?std.os.darwin.MachTask = null, |
| | 313 | }; |
| | 314 | |
| 306 | /// When allocating, the ideal_capacity is calculated by | 315 | /// When allocating, the ideal_capacity is calculated by |
| 307 | /// actual_capacity + (actual_capacity / ideal_factor) | 316 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 308 | const ideal_factor = 3; | 317 | const ideal_factor = 3; |
| ... | @@ -1085,14 +1094,16 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { | ... | @@ -1085,14 +1094,16 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { |
| 1085 | try Atom.resolveRelocations(self, atom_index, relocs.items, code); | 1094 | try Atom.resolveRelocations(self, atom_index, relocs.items, code); |
| 1086 | } | 1095 | } |
| 1087 | | 1096 | |
| 1088 | if (self.base.child_pid) |pid| blk: { | 1097 | if (is_hot_update_compatible) { |
| 1089 | const task = self.mach_task orelse { | 1098 | if (self.base.child_pid) |pid| blk: { |
| 1090 | log.warn("cannot hot swap: no Mach task acquired for child process with pid {d}", .{pid}); | 1099 | const task = self.hot_state.mach_task orelse { |
| 1091 | break :blk; | 1100 | log.warn("cannot hot swap: no Mach task acquired for child process with pid {d}", .{pid}); |
| 1092 | }; | 1101 | break :blk; |
| 1093 | self.updateAtomInMemory(task, section.segment_index, sym.n_value, code) catch |err| { | 1102 | }; |
| 1094 | log.warn("cannot hot swap: writing to memory failed: {s}", .{@errorName(err)}); | 1103 | self.updateAtomInMemory(task, section.segment_index, sym.n_value, code) catch |err| { |
| 1095 | }; | 1104 | log.warn("cannot hot swap: writing to memory failed: {s}", .{@errorName(err)}); |
| | 1105 | }; |
| | 1106 | } |
| 1096 | } | 1107 | } |
| 1097 | | 1108 | |
| 1098 | try self.base.file.?.pwriteAll(code, file_offset); | 1109 | try self.base.file.?.pwriteAll(code, file_offset); |
| ... | @@ -3812,9 +3823,11 @@ pub fn allocatedVirtualSize(self: *MachO, start: u64) u64 { | ... | @@ -3812,9 +3823,11 @@ pub fn allocatedVirtualSize(self: *MachO, start: u64) u64 { |
| 3812 | } | 3823 | } |
| 3813 | | 3824 | |
| 3814 | pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void { | 3825 | pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void { |
| | 3826 | if (!is_hot_update_compatible) return; |
| | 3827 | |
| 3815 | const mach_task = try std.os.darwin.machTaskForPid(pid); | 3828 | const mach_task = try std.os.darwin.machTaskForPid(pid); |
| 3816 | log.debug("Mach task for pid {d}: {any}", .{ pid, mach_task }); | 3829 | log.debug("Mach task for pid {d}: {any}", .{ pid, mach_task }); |
| 3817 | self.mach_task = mach_task; | 3830 | self.hot_state.mach_task = mach_task; |
| 3818 | | 3831 | |
| 3819 | // TODO start exception handler in another thread | 3832 | // TODO start exception handler in another thread |
| 3820 | | 3833 | |
| ... | @@ -3823,6 +3836,8 @@ pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void { | ... | @@ -3823,6 +3836,8 @@ pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void { |
| 3823 | } | 3836 | } |
| 3824 | | 3837 | |
| 3825 | pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { | 3838 | pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { |
| | 3839 | if (!is_hot_update_compatible) return; |
| | 3840 | |
| 3826 | _ = pid; | 3841 | _ = pid; |
| 3827 | | 3842 | |
| 3828 | // TODO stop exception handler | 3843 | // TODO stop exception handler |
| ... | @@ -3830,7 +3845,7 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { | ... | @@ -3830,7 +3845,7 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { |
| 3830 | // TODO see comment in ptraceAttach | 3845 | // TODO see comment in ptraceAttach |
| 3831 | // try std.os.ptrace(std.os.darwin.PT.DETACH, pid, 0, 0); | 3846 | // try std.os.ptrace(std.os.darwin.PT.DETACH, pid, 0, 0); |
| 3832 | | 3847 | |
| 3833 | self.mach_task = null; | 3848 | self.hot_state.mach_task = null; |
| 3834 | } | 3849 | } |
| 3835 | | 3850 | |
| 3836 | pub fn makeStaticString(bytes: []const u8) [16]u8 { | 3851 | pub fn makeStaticString(bytes: []const u8) [16]u8 { |