| ... | @@ -275,10 +275,16 @@ potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, | ... | @@ -275,10 +275,16 @@ potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, |
| 275 | /// Value is the number of PO dependencies of this AnalUnit. | 275 | /// Value is the number of PO dependencies of this AnalUnit. |
| 276 | /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. | 276 | /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. |
| 277 | outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, | 277 | outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, |
| 278 | /// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0. | 278 | /// This is the set of all `AnalUnit`s in `outdated` whose PO dependency count is 0. |
| 279 | /// Such `AnalUnit`s are ready for immediate re-analysis. | 279 | /// Such `AnalUnit`s are ready for immediate re-analysis. |
| 280 | /// See `findOutdatedToAnalyze` for details. | 280 | /// See `findOutdatedToAnalyze` for details. |
| 281 | outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, | 281 | outdated_ready: struct { |
| | 282 | /// These are separate from other units because it allows `findOutdatedToAnalyze` to prioritize |
| | 283 | /// functions, which is useful because it means they will be sent to codegen more quickly. |
| | 284 | funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), |
| | 285 | /// Does not contain `.func` units. |
| | 286 | other: std.AutoArrayHashMapUnmanaged(AnalUnit, void), |
| | 287 | } = .{ .funcs = .empty, .other = .empty }, |
| 282 | /// This contains a list of AnalUnit whose analysis or codegen failed, but the | 288 | /// This contains a list of AnalUnit whose analysis or codegen failed, but the |
| 283 | /// failure was something like running out of disk space, and trying again may | 289 | /// failure was something like running out of disk space, and trying again may |
| 284 | /// succeed. On the next update, we will flush this list, marking all members of | 290 | /// succeed. On the next update, we will flush this list, marking all members of |
| ... | @@ -2835,7 +2841,8 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2835,7 +2841,8 @@ pub fn deinit(zcu: *Zcu) void { |
| 2835 | | 2841 | |
| 2836 | zcu.potentially_outdated.deinit(gpa); | 2842 | zcu.potentially_outdated.deinit(gpa); |
| 2837 | zcu.outdated.deinit(gpa); | 2843 | zcu.outdated.deinit(gpa); |
| 2838 | zcu.outdated_ready.deinit(gpa); | 2844 | zcu.outdated_ready.funcs.deinit(gpa); |
| | 2845 | zcu.outdated_ready.other.deinit(gpa); |
| 2839 | zcu.retryable_failures.deinit(gpa); | 2846 | zcu.retryable_failures.deinit(gpa); |
| 2840 | | 2847 | |
| 2841 | zcu.test_functions.deinit(gpa); | 2848 | zcu.test_functions.deinit(gpa); |
| ... | @@ -3065,6 +3072,7 @@ pub fn markDependeeOutdated( | ... | @@ -3065,6 +3072,7 @@ pub fn markDependeeOutdated( |
| 3065 | marked_po: enum { not_marked_po, marked_po }, | 3072 | marked_po: enum { not_marked_po, marked_po }, |
| 3066 | dependee: InternPool.Dependee, | 3073 | dependee: InternPool.Dependee, |
| 3067 | ) !void { | 3074 | ) !void { |
| | 3075 | const gpa = zcu.comp.gpa; |
| 3068 | deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | 3076 | deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); |
| 3069 | var it = zcu.intern_pool.dependencyIterator(dependee); | 3077 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3070 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | 3078 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); |
| ... | @@ -3078,7 +3086,10 @@ pub fn markDependeeOutdated( | ... | @@ -3078,7 +3086,10 @@ pub fn markDependeeOutdated( |
| 3078 | deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | 3086 | deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); |
| 3079 | if (po_dep_count.* == 0) { | 3087 | if (po_dep_count.* == 0) { |
| 3080 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | 3088 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); |
| 3081 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | 3089 | switch (depender.unwrap()) { |
| | 3090 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), |
| | 3091 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), |
| | 3092 | } |
| 3082 | } | 3093 | } |
| 3083 | }, | 3094 | }, |
| 3084 | } | 3095 | } |
| ... | @@ -3094,14 +3105,17 @@ pub fn markDependeeOutdated( | ... | @@ -3094,14 +3105,17 @@ pub fn markDependeeOutdated( |
| 3094 | }, | 3105 | }, |
| 3095 | }; | 3106 | }; |
| 3096 | try zcu.outdated.putNoClobber( | 3107 | try zcu.outdated.putNoClobber( |
| 3097 | zcu.gpa, | 3108 | gpa, |
| 3098 | depender, | 3109 | depender, |
| 3099 | new_po_dep_count, | 3110 | new_po_dep_count, |
| 3100 | ); | 3111 | ); |
| 3101 | deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); | 3112 | deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); |
| 3102 | if (new_po_dep_count == 0) { | 3113 | if (new_po_dep_count == 0) { |
| 3103 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | 3114 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); |
| 3104 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | 3115 | switch (depender.unwrap()) { |
| | 3116 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), |
| | 3117 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), |
| | 3118 | } |
| 3105 | } | 3119 | } |
| 3106 | // If this is a Decl and was not previously PO, we must recursively | 3120 | // If this is a Decl and was not previously PO, we must recursively |
| 3107 | // mark dependencies on its tyval as PO. | 3121 | // mark dependencies on its tyval as PO. |
| ... | @@ -3119,6 +3133,7 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ... | @@ -3119,6 +3133,7 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3119 | } | 3133 | } |
| 3120 | /// Assumes that `zcu.outdated_lock` is already held exclusively. | 3134 | /// Assumes that `zcu.outdated_lock` is already held exclusively. |
| 3121 | fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { | 3135 | fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| | 3136 | const gpa = zcu.comp.gpa; |
| 3122 | deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); | 3137 | deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); |
| 3123 | var it = zcu.intern_pool.dependencyIterator(dependee); | 3138 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3124 | while (it.next()) |depender| { | 3139 | while (it.next()) |depender| { |
| ... | @@ -3129,7 +3144,10 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ... | @@ -3129,7 +3144,10 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3129 | deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | 3144 | deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); |
| 3130 | if (po_dep_count.* == 0) { | 3145 | if (po_dep_count.* == 0) { |
| 3131 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | 3146 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); |
| 3132 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | 3147 | switch (depender.unwrap()) { |
| | 3148 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), |
| | 3149 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), |
| | 3150 | } |
| 3133 | } | 3151 | } |
| 3134 | continue; | 3152 | continue; |
| 3135 | } | 3153 | } |
| ... | @@ -3167,7 +3185,8 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ... | @@ -3167,7 +3185,8 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3167 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. | 3185 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. |
| 3168 | /// | 3186 | /// |
| 3169 | /// Assumes that `zcu.outdated_lock` is already held exclusively. | 3187 | /// Assumes that `zcu.outdated_lock` is already held exclusively. |
| 3170 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { | 3188 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) Allocator.Error!void { |
| | 3189 | const gpa = zcu.comp.gpa; |
| 3171 | const ip = &zcu.intern_pool; | 3190 | const ip = &zcu.intern_pool; |
| 3172 | const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) { | 3191 | const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) { |
| 3173 | .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies | 3192 | .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies |
| ... | @@ -3181,10 +3200,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni | ... | @@ -3181,10 +3200,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 3181 | var it = ip.dependencyIterator(dependee); | 3200 | var it = ip.dependencyIterator(dependee); |
| 3182 | while (it.next()) |po| { | 3201 | while (it.next()) |po| { |
| 3183 | if (zcu.outdated.getPtr(po)) |po_dep_count| { | 3202 | if (zcu.outdated.getPtr(po)) |po_dep_count| { |
| 3184 | // This dependency is already outdated, but it now has one more PO | 3203 | // This dependency is already outdated, but it now has one more PO dependency. |
| 3185 | // dependency. | | |
| 3186 | if (po_dep_count.* == 0) { | 3204 | if (po_dep_count.* == 0) { |
| 3187 | _ = zcu.outdated_ready.swapRemove(po); | 3205 | switch (po.unwrap()) { |
| | 3206 | .func => |func| _ = zcu.outdated_ready.funcs.swapRemove(func), |
| | 3207 | else => _ = zcu.outdated_ready.other.swapRemove(po), |
| | 3208 | } |
| 3188 | } | 3209 | } |
| 3189 | po_dep_count.* += 1; | 3210 | po_dep_count.* += 1; |
| 3190 | deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); | 3211 | deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); |
| ... | @@ -3196,7 +3217,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni | ... | @@ -3196,7 +3217,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 3196 | deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); | 3217 | deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); |
| 3197 | continue; | 3218 | continue; |
| 3198 | } | 3219 | } |
| 3199 | try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); | 3220 | try zcu.potentially_outdated.putNoClobber(gpa, po, 1); |
| 3200 | deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); | 3221 | deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); |
| 3201 | // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. | 3222 | // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. |
| 3202 | try zcu.markTransitiveDependersPotentiallyOutdated(po); | 3223 | try zcu.markTransitiveDependersPotentiallyOutdated(po); |
| ... | @@ -3208,10 +3229,20 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni | ... | @@ -3208,10 +3229,20 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 3208 | /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because | 3229 | /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because |
| 3209 | /// recursive analysis can cause over-analysis on incremental updates. | 3230 | /// recursive analysis can cause over-analysis on incremental updates. |
| 3210 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { | 3231 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3211 | // MLUGG TODO: priorize `func` units, just like we used to do in the Compilation job queue. | 3232 | // We prioritize functions, because the sooner they get analyzed, the sooner they can be send to |
| | 3233 | // the codegen backend and linker, which are usually running in parallel (so this can increase |
| | 3234 | // parallelism). |
| | 3235 | // TODO: perhaps we should also experiment with *avoiding* functions if the codegen/link queue |
| | 3236 | // is backed up (for instance due to a very large function). That could help minimize blocking |
| | 3237 | // on the main thread in `CodegenTaskPool.start` waiting for the linker to catch up. |
| | 3238 | if (zcu.outdated_ready.funcs.count() > 0) { |
| | 3239 | const unit: AnalUnit = .wrap(.{ .func = zcu.outdated_ready.funcs.keys()[0] }); |
| | 3240 | log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); |
| | 3241 | return unit; |
| | 3242 | } |
| 3212 | | 3243 | |
| 3213 | if (zcu.outdated_ready.count() > 0) { | 3244 | if (zcu.outdated_ready.other.count() > 0) { |
| 3214 | const unit = zcu.outdated_ready.keys()[0]; | 3245 | const unit = zcu.outdated_ready.other.keys()[0]; |
| 3215 | log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); | 3246 | log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); |
| 3216 | return unit; | 3247 | return unit; |
| 3217 | } | 3248 | } |
| ... | @@ -3502,13 +3533,12 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { | ... | @@ -3502,13 +3533,12 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { |
| 3502 | assert(func == ip.unwrapCoercedFunc(func)); // analyze the body of the original function, not a coerced one | 3533 | assert(func == ip.unwrapCoercedFunc(func)); // analyze the body of the original function, not a coerced one |
| 3503 | if (ip.setWantRuntimeFnAnalysis(io, func)) { | 3534 | if (ip.setWantRuntimeFnAnalysis(io, func)) { |
| 3504 | // This is the first reference to this function, so we must ensure it will be analyzed. | 3535 | // This is the first reference to this function, so we must ensure it will be analyzed. |
| 3505 | const unit: AnalUnit = .wrap(.{ .func = func }); | | |
| 3506 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | 3536 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); |
| 3507 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | 3537 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); |
| 3508 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | 3538 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); |
| 3509 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); | 3539 | try zcu.outdated_ready.funcs.ensureUnusedCapacity(gpa, 1); |
| 3510 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); | 3540 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .func = func }), 0); |
| 3511 | zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); | 3541 | zcu.outdated_ready.funcs.putAssumeCapacityNoClobber(func, {}); |
| 3512 | } | 3542 | } |
| 3513 | } | 3543 | } |
| 3514 | | 3544 | |
| ... | @@ -3522,11 +3552,11 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { | ... | @@ -3522,11 +3552,11 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { |
| 3522 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | 3552 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); |
| 3523 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | 3553 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); |
| 3524 | try zcu.outdated.ensureUnusedCapacity(gpa, 2); | 3554 | try zcu.outdated.ensureUnusedCapacity(gpa, 2); |
| 3525 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); | 3555 | try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 2); |
| 3526 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); | 3556 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); |
| 3527 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); | 3557 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); |
| 3528 | zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); | 3558 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); |
| 3529 | zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); | 3559 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); |
| 3530 | } | 3560 | } |
| 3531 | } | 3561 | } |
| 3532 | | 3562 | |
| ... | @@ -3540,9 +3570,9 @@ pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allo | ... | @@ -3540,9 +3570,9 @@ pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allo |
| 3540 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); | 3570 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); |
| 3541 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); | 3571 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); |
| 3542 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | 3572 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); |
| 3543 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); | 3573 | try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); |
| 3544 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); | 3574 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); |
| 3545 | zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); | 3575 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(unit, {}); |
| 3546 | } | 3576 | } |
| 3547 | | 3577 | |
| 3548 | /// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. | 3578 | /// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. |
| ... | @@ -3552,7 +3582,15 @@ pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { | ... | @@ -3552,7 +3582,15 @@ pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { |
| 3552 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); | 3582 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); |
| 3553 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); | 3583 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); |
| 3554 | if (zcu.outdated.fetchSwapRemove(unit)) |kv| { | 3584 | if (zcu.outdated.fetchSwapRemove(unit)) |kv| { |
| 3555 | if (kv.value == 0) assert(zcu.outdated_ready.swapRemove(unit)); | 3585 | const was_ready = switch (unit.unwrap()) { |
| | 3586 | .func => |func| zcu.outdated_ready.funcs.swapRemove(func), |
| | 3587 | else => zcu.outdated_ready.other.swapRemove(unit), |
| | 3588 | }; |
| | 3589 | if (kv.value == 0) { |
| | 3590 | assert(was_ready); |
| | 3591 | } else { |
| | 3592 | assert(!was_ready); |
| | 3593 | } |
| 3556 | return true; | 3594 | return true; |
| 3557 | } else if (zcu.potentially_outdated.swapRemove(unit)) { | 3595 | } else if (zcu.potentially_outdated.swapRemove(unit)) { |
| 3558 | return true; | 3596 | return true; |