Skip to content

0.19.0

Latest

Choose a tag to compare

@github-actions github-actions released this 07 Sep 10:37
61f0628

0.19.0

A minor release on top of 0.17.1, carrying three pieces of work: the ABI model no longer drags in the symbol index and the demangler (source-breaking β€” the migration list is below), dump and interface got 17–23% faster, and a class's vtable members are attributed correctly when the linker has folded several method bodies onto one address. There is no 0.18.0 release; everything written under that number ships here.

What's new

  • Reading ABI descriptors no longer builds the image's symbol index. MachOSwiftSection now depends on MachOBase alone β€” no symbol index, no demangler β€” so touching a method descriptor's implementation pointer costs pointer arithmetic instead of demangling every symbol in the image on first access. Symbol attribution moved one layer up, to SwiftInspection. Two new library products come with the split: MachOBase (readers, resolvers, pointers) and MachOFoundation (that plus the symbol index and dependency resolution).
  • dump and interface are faster with no flags to set. The speedup comes from where the demangler runs, so it applies to every reader path and every output style. It needs macOS 15 / iOS 18 (or the aligned tvOS 18 / watchOS 11 / visionOS 2) at runtime; below that, and off Darwin, everything behaves as in 0.17.1.
  • --jobs N (diff, evolution) β€” how many versions to index at once. Defaults to the processor count; --jobs 1 restores the previous one-at-a-time order. Results are identical either way. In the library it is prepare(maximumConcurrentPreparations:).
  • Console diagnostics name their input. diff prefixes its lines [old] / [new], evolution prefixes each version's label, so a warning from a five-version run is attributable. stderr only, as before.
  • MACHO_SWIFT_SECTION_LARGE_STACK_EXECUTOR=0 turns the faster path off process-wide, for a host that manages its own task executor. 0 / false / no / off all mean off; anything else, or unset, means on.

Fixes

  • A class's vtable members no longer borrow a nested type's names. Identical code folding merges byte-identical method bodies onto one address β€” SwiftUICore has one carrying 2878 symbols β€” and a member's name used to be read from there, so SwiftUI.GraphHost printed three of its nested GraphHost.Data's coroutine resume functions as its own methods. Names now come from each member's own method-descriptor symbol, which folding cannot reach. On SwiftUICore (iOS 18.5 arm64): 828 declaration lines change, all 7 nested-type bleeds are gone with none introduced, and Symbol not found drops from 358 to 0.
  • Two new comments where a name cannot be trusted. The ~28% of slots carrying no method-descriptor symbol still fall back to the implementation address; when that address is folded, the output now says so (// Attribution: ambiguous β€” N symbols folded at this address) rather than presenting a guess as fact. A slot whose body was removed by dead-method elimination is annotated instead of failing to resolve. Both comments are always on; their wording and the N count are being tuned for the next release.

Breaking

Source level β€” this package is distributed as source, so every downstream recompiles:

  • descriptor.implementationSymbols(in: machO) β€” drop the try, add import SwiftInspection.
  • descriptor.implementationSymbols(in: context) β€” removed. Use try descriptor.implementationAddress(in: context) for the location.
  • Symbols.resolve(from:in:) β€” removed. Call machO.symbols(offset:) (MachOSymbols).
  • symbols(offset:) async β€” removed. It was identical to the synchronous form, and an async caller bound to it and then demanded await.
  • MachOSymbols.Symbol / .Symbols / .SymbolOrElement β€” now MachOResolving.…, or unqualified.
  • import MachOSymbolPointers β€” remove it; SymbolOrElementPointer lives in MachOPointers.
  • ResilientWitness.implementationOffset is Int?, and implementationAddress(in:) returns String?.
  • A file that reached SymbolIndexStore, DemangledSymbol or DependencyClosure through import MachOSwiftSection alone now needs import MachOFoundation, and its target must declare that product (.product(name: "MachOFoundation", package: "MachOSwiftSection")). Those types used to arrive through a re-export, so no product existed for them β€” and reaching a module through the build directory without declaring it works by accident in a monolithic SwiftPM build, then fails under explicit modules.

Measured

Release build, host dyld shared cache, macOS 26.5.2 on a 10-core Apple Silicon Mac.

SwiftUICore SwiftUI
dump 48.8 s β†’ 40.6 s 79.4 s β†’ 61.3 s
interface 56.4 s β†’ 47.0 s 87.5 s β†’ 71.2 s

evolution over three archived SwiftUI caches (macOS 15.5 / 26.5.2 / 27.0 beta 6) roughly halves with the default --jobs: --interface 307 s β†’ 152 s, lineage report 282 s β†’ 139 s.

Compatibility

  • dump / interface output changes in two places, both deliberate: the vtable attribution fix above, and β€” only under --emit-member-addresses β€” a resilient witness with a null implementation pointer no longer gets an address comment (the old line printed the pointer field's own position as if it were code). Everything else is byte-identical to 0.17.1, verified with the rendering A/B harness.
  • Dependency floor: swift-demangling 0.6.3 ..< 0.7.0 (was 0.6.0 ..< 0.7.0). Do not pin 0.6.1 β€” it slowed dump / interface 3–4Γ— and 0.6.2 fixed it. Other pins unchanged from 0.17.1.
  • Snapshot formatVersion unchanged.

Requirements

  • Swift 6.2+
  • Xcode 26.0+

Full design and measurements: evolution proposals 0018, 0019 and 0020; implementation notes SelfContainedABILayer.md and LargeStackTaskExecutorAdoption.md.