| ... | @@ -62,10 +62,18 @@ const want_multi_threaded = true; | ... | @@ -62,10 +62,18 @@ const want_multi_threaded = true; |
| 62 | /// Whether a single-threaded intern pool impl is in use. | 62 | /// Whether a single-threaded intern pool impl is in use. |
| 63 | pub const single_threaded = builtin.single_threaded or !want_multi_threaded; | 63 | pub const single_threaded = builtin.single_threaded or !want_multi_threaded; |
| 64 | | 64 | |
| | 65 | /// A `TrackedInst.Index` provides a single, unchanging reference to a ZIR instruction across a whole |
| | 66 | /// compilation. From this index, you can acquire a `TrackedInst`, which containss a reference to both |
| | 67 | /// the file which the instruction lives in, and the instruction index itself, which is updated on |
| | 68 | /// incremental updates by `Zcu.updateZirRefs`. |
| 65 | pub const TrackedInst = extern struct { | 69 | pub const TrackedInst = extern struct { |
| 66 | file: FileIndex, | 70 | file: FileIndex, |
| 67 | inst: Zir.Inst.Index, | 71 | inst: Zir.Inst.Index, |
| 68 | | 72 | |
| | 73 | /// It is possible on an incremental update that we "lose" a ZIR instruction: some tracked `%x` in |
| | 74 | /// the old ZIR failed to map to any `%y` in the new ZIR. For this reason, we actually store values |
| | 75 | /// of type `MaybeLost`, which uses `ZirIndex.lost` to represent this case. `Index.resolve` etc |
| | 76 | /// return `null` when the `TrackedInst` being resolved has been lost. |
| 69 | pub const MaybeLost = extern struct { | 77 | pub const MaybeLost = extern struct { |
| 70 | file: FileIndex, | 78 | file: FileIndex, |
| 71 | inst: ZirIndex, | 79 | inst: ZirIndex, |
| ... | @@ -244,14 +252,17 @@ pub fn trackZir( | ... | @@ -244,14 +252,17 @@ pub fn trackZir( |
| 244 | return index; | 252 | return index; |
| 245 | } | 253 | } |
| 246 | | 254 | |
| | 255 | /// At the start of an incremental update, we update every entry in `tracked_insts` to include |
| | 256 | /// the new ZIR index. Once this is done, we must update the hashmap metadata so that lookups |
| | 257 | /// return correct entries where they already exist. |
| 247 | pub fn rehashTrackedInsts( | 258 | pub fn rehashTrackedInsts( |
| 248 | ip: *InternPool, | 259 | ip: *InternPool, |
| 249 | gpa: Allocator, | 260 | gpa: Allocator, |
| 250 | /// TODO: maybe don't take this? it doesn't actually matter, only one thread is running at this point | | |
| 251 | tid: Zcu.PerThread.Id, | 261 | tid: Zcu.PerThread.Id, |
| 252 | ) Allocator.Error!void { | 262 | ) Allocator.Error!void { |
| | 263 | assert(tid == .main); // we shouldn't have any other threads active right now |
| | 264 | |
| 253 | // TODO: this function doesn't handle OOM well. What should it do? | 265 | // TODO: this function doesn't handle OOM well. What should it do? |
| 254 | // Indeed, what should anyone do when they run out of memory? | | |
| 255 | | 266 | |
| 256 | // We don't lock anything, as this function assumes that no other thread is | 267 | // We don't lock anything, as this function assumes that no other thread is |
| 257 | // accessing `tracked_insts`. This is necessary because we're going to be | 268 | // accessing `tracked_insts`. This is necessary because we're going to be |
| ... | @@ -795,6 +806,14 @@ const Local = struct { | ... | @@ -795,6 +806,14 @@ const Local = struct { |
| 795 | /// This state is fully local to the owning thread and does not require any | 806 | /// This state is fully local to the owning thread and does not require any |
| 796 | /// atomic access. | 807 | /// atomic access. |
| 797 | mutate: struct { | 808 | mutate: struct { |
| | 809 | /// When we need to allocate any long-lived buffer for mutating the `InternPool`, it is |
| | 810 | /// allocated into this `arena` (for the `Id` of the thread performing the mutation). An |
| | 811 | /// arena is used to avoid contention on the GPA, and to ensure that any code which retains |
| | 812 | /// references to old state remains valid. For instance, when reallocing hashmap metadata, |
| | 813 | /// a racing lookup on another thread may still retain a handle to the old metadata pointer, |
| | 814 | /// so it must remain valid. |
| | 815 | /// This arena's lifetime is tied to that of `Compilation`, although it can be cleared on |
| | 816 | /// garbage collection (currently vaporware). |
| 798 | arena: std.heap.ArenaAllocator.State, | 817 | arena: std.heap.ArenaAllocator.State, |
| 799 | | 818 | |
| 800 | items: ListMutate, | 819 | items: ListMutate, |