[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.