swift
1e430fb9 - [Concurrency] Redesign TaskDeadlineStatusRecord: store real Instant in a Swift box

Commit
105 days ago
[Concurrency] Redesign TaskDeadlineStatusRecord: store real Instant in a Swift box The old record stored a deadline as two Int64s (seconds + attoseconds) plus a tagged union of "SystemClockID raw value or _ClockIDBox". That lost fidelity for custom clocks whose Instant isn't Duration-shaped (the (seconds, atto) representation was synthesized via clock.now.duration(to: expiration) at push time and reconstructed with drift at read time) and required contorted SIL ownership on the custom-clock box that never actually built. New shape: the record is two words - a Metadata pointer for the caller's Clock type C and a retained HeapObject pointer to a Swift _ClockBox<C> that stores both the clock instance and the deadline instant losslessly. Identity and comparison move to Swift: - _AnyClockBox is a non-generic base class with a virtual method hasSameClock(as: _AnyClockBox) -> Bool. - _ClockBox<C: Clock & Identifiable> is the concrete subclass; its override does an unchecked downcast (the runtime has pointer-equal- checked ClockType metadata before dispatching, guaranteeing both boxes share C) and compares clock.id. - The runtime bridges into Swift via a single @_silgen_name function _task_deadline_boxesSameClock(a: AnyObject, b: AnyObject) -> Bool. Because both args are class-typed at the ABI level, no metadata / witness-table plumbing is needed on the C++ side. Runtime entry points: - swift_task_pushDeadline(clockType, box) - installs the record and consumes the +1 on the box. The Swift-side subsumption fast-path in withDeadline (committed 9f4f1cdaa3a) handles nesting, so the runtime just installs. - swift_task_popDeadline(record) - unlinks and swift_releases the box. The _ClockBox destructor releases the clock and the Instant transitively; no C++ destroy callback needed. - swift_task_findNearestDeadlineForClock(queryClock, clockType, ...) - walks the chain filtering by ClockType pointer-equal, then dispatches into _task_deadline_boxesSameClock. The trailing WT args are kept in the signature to mirror the Swift-generic ABI shape but are unused by the current path. Builtins take four raw pointers each (metatype, box or query-box, and the two unused WT pointers on find). This resolves the pending SIL ownership issue - no more owned Builtin.NativeObject? shared between push (consume) and find (borrow), find takes a raw pointer. Swift-side simplifications: - _findNearestDeadline<C> now returns C.Instant? directly. - Task.activeDeadline(for:) is a one-liner delegating to it. - Task.hasActiveDeadline stays as the flag-only fast path. - All the seconds/atto reconstruction machinery is gone. - The withDeadline subsumption fast-path compares C.Instant via Comparable (guaranteed by InstantProtocol) directly, no _DeadlineComponents. Deleted: - _ClockIDBox, _swift_task_deadlineClockIDsEqual (Swift + C++). - compareDeadline, _swift_task_deadlineComponents (C++). - _DeadlineComponents, _encodeClockIdentityForPush, _instantComponents (Swift). - The runtime-side subsumption walk in swift_task_pushDeadlineImpl. Build note: had to change one call site in _swift_task_hasCancelledScope from `withStatusRecordLock(task, lambda)` to `::withStatusRecordLock(task, lambda)` - the file-scope static template at line 143 wasn't visible via unqualified lookup from inside a swift::-qualified function definition. The :: prefix forces lookup in the enclosing namespace where the template lives. Concurrency stdlib builds cleanly.
Author
Parents
Loading