Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ランタイムライブラリのbackward-deploymentの仕組み

7a4968fbcd56e81f95a4f3c186141b52?s=47 Yuta Saito
September 24, 2021

 ランタイムライブラリのbackward-deploymentの仕組み

[わいわいswiftc #30 オンライン - connpass](https://iosdiscord.connpass.com/event/223396/)

7a4968fbcd56e81f95a4f3c186141b52?s=128

Yuta Saito

September 24, 2021
Tweet

Transcript

  1. ϥϯλΠϜϥΠϒϥϦͷbackward- deploymentͷ࢓૊Έ Θ͍Θ͍swiftc #30 @kateinoigakukun 1

  2. όοΫσϓϩΠ͕ࠓΞπ͍ 2

  3. Ͳ͏ͯ͠ࠓʁ • async / await ͸͍·ͷͱ͜Ζ࠷৽ͷOSͰ͔͠࢖͑ͳ͍͚ Ͳ… • ݹ͍OSͰ΋࢖͑Δ͔΋ʂͱ͍͏࿩͕ग़͖ͯͨ 3

  4. ! • Ξπ͗ͯ͢εϨου͕രൃ • ͦͯ͠ϩοΫ͞Εͨ… https://forums.swift.org/t/will-swift-concurrency-deploy-back-to-older-oss/49370 4

  5. ͓͠ͳ͕͖ 1. Swiftͷ࣮ߦʹඞཁͳ΋ͷ 2. ABI Stability 3. ͳͥόοΫσϓϩΠ͕ඞཁʁ 4. όοΫσϓϩΠͷ࢓૊Έ

    5. ConcurrencyϞδϡʔϧͷόοΫσϓϩΠ 5
  6. ϥϯλΠϜͷ໾ׂ • Swiftͷ࣮ߦʹ͸ϥϯλΠϜϥΠϒϥϦ͕ඞཁ • libswiftCore.dylib • ݴޠͷ࣮ߦ࣌ػೳΛఏڙ • ಈతΩϟετ •

    ARC • etc ... 6
  7. ABI όΠφϦಉ͕࢜Ծఆ͢Δ໿ଋ • ࿐ग़͢ΔγϯϘϧ • ݺͼग़͠ن໿ • ϝϞϦϞσϧ • σʔλߏ଄

    • etc ... 7
  8. SwiftͷABI Stability ίϯύΠϥͷੜ੒όΠφϦɺϥϯλΠϜͷABIʹ͍ͭͯ ޓ׵ੑΛอͭ໿ଋ • લํ/ޙํ ͲͪΒʹ΋ޓ׵ • ޙํͷํ͕େࣄɻલํ͸࠷ѱ෦෼తͰ΋OK •

    ABI Stability Manifestʹৄ͍͠ن໿͕͋Δ https://github.com/apple/swift/blob/main/docs/ABIStabilityManifesto.md 8
  9. ABI Stability͕Մೳʹ͢Δ͜ͱ ྫ • Swift 5.0ͰίϯύΠϧͨ͠ϥΠϒϥϦ͕ɺ Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦͰ࢖͑Δɻ • Swift

    5.0ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ Swift 5.1ͷϥϯλΠϜͰಈ͘ɻ • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ Swift 5.0ͷϥϯλΠϜͰಈ͘ɻ 9
  10. ABI Stabilizeલ (~ Swift 5.0) • ֤ΞϓϦ͕ϥϯλΠϜϥΠϒϥϦΛಉࠝ • ΞϓϦͱϥϯλΠϜͷݴޠόʔδϣϯ͕ৗʹҰக ./My.app

    ├── Frameworks │ └── libswiftCore.dylib ├── Info.plist ├── My └── _CodeSignature 10
  11. ABI Stabilizeલ (Swift 5.0 ~) • iOS 13ɺmacOS 10.14.4 ͔ΒOSࣗମʹಉࠝ

    • ϥΠϒϥϦΛల։͢ΔϝϞϦΛΞϓϦؒͰڞ༗ • ΞϓϦͷόϯυϧαΠζ΋ݮͬͯخ͍͠ • ͕ɺϥϯλΠϜͷόʔδϣϯ͕OS͝ͱʹݻఆ͞Εͯ͠·ͬͨ 11
  12. ϥϯλΠϜ͕OSʹೖΔ͜ͱͰى͜Δ໰୊ ΞϓϦ͕࢖͏ݴޠόʔδϣϯͱϥϯλΠϜόʔδϣϯ͕ඞͣ͠ ΋Ұக͠ͳ͍ ྫ • Swift 5.0ͰίϯύΠϧͨ͠ΞϓϦΛɺ Swift 5.1ͷϥϯλΠϜͰಈ͔͢ɻ ->

    ϥϯλΠϜͷޙํޓ׵ੑ • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦΛɺ Swift 5.0ͷϥϯλΠϜͰಈ͔͢ɻ -> ϥϯλΠϜͷલํޓ׵ੑ 12
  13. ϥϯλΠϜͷޙํޓ׵ੑ ݹ͍SwiftΞϓϦΛ৽͍͠SwiftϥϯλΠϜͰಈ͔͢ • ΞοϓσʔτΛadditiveͳมߋ͚ͩʹ͢Ε͹OK • γϯϘϧͷ࡟আͱ͔ɺηϚϯςΟΫεͷมߋ͸μϝ 13

  14. ϥϯλΠϜͷޙํޓ׵ੑ additiveͰͳ͍มߋ͕ೖΔͱOS͝ͱʹڍಈ͕มΘͬͯࠔΔ • μΠφϛοΫΩϟετͷڍಈ͕มΘͬͯࠔͬͨྫ • SR-1999: Inconsistency when casting Optional

    to Any and downcasting to non-Optional • IBLinter Issue #170 14
  15. ϥϯλΠϜͷલํޓ׵ੑ ৽͍͠SwiftΞϓϦΛݹ͍SwiftϥϯλΠϜͰಈ͔͢ • ΞϓϦ͸ݹ͍ϥϯλΠϜ͕஌Βͳ͍ػೳ/ڍಈΛཁٻ͢Δ • όοΫσϓϩΠͷग़൪ 15

  16. SwiftϥϯλΠϜͷόοΫσϓϩΠͷಛ௃ • ΞϓϦίϯύΠϧ࣌ʹ৽͍͠ϥϯλΠϜ࣮૷ͷҰ෦ΛຒΊࠐ Ή • ϥϯλΠϜ͕ݹ͍ͱ͖͸ຒΊࠐ·Ε࣮ͨ૷ʹ੾Γସ͑Δ • ϥϯλΠϜ͕৽͍͕͋͠Δͱ͖͸ຒΊࠐΈ࣮૷Λແࢹ • γϯάϧόΠφϦͱͯ͠഑෍Մೳ

    16
  17. όοΫσϓϩΠͷྲྀΕ # min-deploytarget͔Β࠷খϥϯλΠϜΛܾΊΔ swiftc main.swift -target x86_64-apple-macosx10.15 # OR #

    ࠷খϥϯλΠϜΛ௚઀ࢦఆ swiftc main.swift -runtime-compatibility-version 5.1 17
  18. υϥΠό͕΍Δ͜ͱ libswiftCompatibility51.aΛϦϯΫ swiftc -emit-object main.swift -o main.o ld main.o \

    -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility51.a \ -lswiftCore -o main 18
  19. ϦϯΫޙͷόΠφϦ $ du -h main_5_1_compat 56K main_5_1_compat $ objdump --macho

    --headers main_5_1_compat Sections: Idx Name Size VMA Type 0 __text 00000f9c 0000000100002d64 TEXT 1 __stubs 000000d8 0000000100003d00 TEXT 2 __stub_helper 000000f0 0000000100003dd8 TEXT 3 __swift5_entry 00000004 0000000100003ec8 DATA 4 __const 00000006 0000000100003ecc DATA 5 __cstring 0000009b 0000000100003ed2 DATA 6 __unwind_info 00000090 0000000100003f70 DATA 7 __got 00000008 0000000100004000 DATA 8 __const 00000008 0000000100004008 DATA 9 __objc_imageinfo 00000008 0000000100004010 DATA 10 __la_symbol_ptr 00000090 0000000100008000 DATA 11 __swift51_hooks 000000b8 0000000100008090 DATA 12 __data 00000009 0000000100008148 DATA 13 __bss 000000c8 0000000100008158 BSS $ du -h main 36K main $ objdump --macho --headers main Sections: Idx Name Size VMA Type 0 __text 0000000c 0000000100003fa4 TEXT 1 __swift5_entry 00000004 0000000100003fb0 DATA 2 __const 00000002 0000000100003fb4 DATA 3 __unwind_info 00000048 0000000100003fb8 DATA 4 __objc_imageinfo 00000008 0000000100004000 DATA 19
  20. libswiftCompatibilityX.a ͷਖ਼ମ • όʔδϣϯXͷϥϯλΠϜʹ଍Γͳ͍ɺݱࡏͷόʔδϣϯͷػ ೳΛ࣮૷ • ϑοΫηΫγϣϯʢe.g. __swift51_hooksʣʹΦʔόʔϥΠ υ͢Δؔ਺ϦετΛೖΕΔ 20

  21. ϥϯλΠϜͷΦʔόʔϥΠυػߏ • ΦʔόʔϥΠυग़དྷΔؔ਺ͷϦετʢX Macroʣ • CompatibilityOverrideRuntime.def • େମͷϥϯλΠϜؔ਺͕ొ࿥͞ΕͯΔ • ϑοΫηΫγϣϯʹΦʔόʔϥΠυؔ਺͕ొ࿥͞ΕͯΔͱ

    ͦͬͪΛݺͿ 21
  22. ϥϯλΠϜؔ਺ͷ࣮ଶ #define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \ typedArgs, namedArgs)

    \ attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \ static Override_##name Override; \ static swift_once_t Predicate; \ swift_once( \ &Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \ if (Override != nullptr) \ return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \ swift_##name##Impl); \ return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \ } COMPATIBILITY_OVERRIDE(dynamicCastClass, const void *, , , swift::, (const void *object, const ClassMetadata *targetType), (object, targetType)) https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.h 22
  23. ϥϯλΠϜؔ਺ͷ࣮ଶʢϚΫϩల։ޙʣ const void * swift::swift_dynamicCastClass(const void *object, const ClassMetadata *targetType)

    { static Override_dynamicCastClass Override; static swift_once_t Predicate; swift_once(&Predicate, [](void *) { Override = getOverride_dynamicCastClass(); }, nullptr); if (Override != nullptr) return Override(object, targetType, swift_dynamicCastClassImpl); return swift_dynamicCastClassImpl(object, targetType); } https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.h 23
  24. ϑοΫηΫγϣϯ͔Β OverrideSection ߏ଄ମΛಡΈग़͢ // ϚΠφʔόʔδϣϯΞοϓ͝ͱʹมΘΔ #define COMPATIBILITY_OVERRIDE_SECTION_NAME __swift54_hooks static OverrideSection

    *getOverrideSectionPtr() { static OverrideSection *OverrideSectionPtr; static swift_once_t Predicate; swift_once(&Predicate, [](void *) { size_t Size; OverrideSectionPtr = static_cast<OverrideSection *>( lookupSection("__DATA", COMPATIBILITY_OVERRIDE_SECTION_NAME, &Size)); if (Size < sizeof(OverrideSection)) OverrideSectionPtr = nullptr; }, nullptr); return OverrideSectionPtr; } Override_dynamicCastClass swift::getOverride_dynamicCastClass() { auto *Section = getOverrideSectionPtr(); if (Section == nullptr) return nullptr; return Section->dynamicCastClass; } https://github.com/apple/swift/blob/main/stdlib/public/CompatibilityOverride/CompatibilityOverride.cpp 24
  25. ϑοΫηΫγϣϯ in libswiftCompatibility51.a struct OverrideSection { uintptr_t version; #define OVERRIDE(name,

    ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ Override_ ## name name; #include "CompatibilityOverride.def" }; OverrideSection Swift51Overrides __attribute__((used, section("__DATA,__swift51_hooks"))) = { .version = 0, .conformsToSwiftProtocol = swift51override_conformsToSwiftProtocol, }; 25
  26. ෳ਺ͷݹ͍ϥϯλΠϜΛαϙʔτ͍ͨ͠ͱ͖ • ෳ਺ͷlibswiftCompatibilityX.aΛϦϯΫ͢Ε͹OK • ϥϯλΠϜ͸ࣗ਎ͷόʔδϣϯ޲͚ͷϑοΫηΫγϣϯ͔͠ ಡ·ͳ͍ͷͰׯব͠ͳ͍ swiftc main.swift -runtime-compatibility-version 5.0

    # υϥΠό͕ˣΛൃߦ ld main.o \ -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility50.a \ -force_load /path/to/toolchain/usr/lib/swift/macosx/libswiftCompatibility51.a \ -lswiftCore -o main 26
  27. ίϯύΠϥ։ൃ؀ڥͰͷϋοΫ • όΠφϦ͸OSಉࠝ(/usr/lib/swift/libswiftCore.dylib)ΛϦϯΫ ͯ͠Δ • ։ൃத͸ίϯύΠϥόʔδϣϯͱҰகͨ͠ϥϯλΠϜ͕खݩ ʹ͋Δ • ։ൃத͸OSಉࠝ͡Όͳ͍ϥϯλΠϜΛ࢖͍͍ͨ 27

  28. DYLD_LIBRARY_PATH ؀ڥม਺ • DYLD_LIBRARY_PATH=/path/to/lib_dir Ληοτͯ͠όΠ φϦΛىಈ͢Δͱɺϩʔυ͢ΔμΠφϛοΫϥΠϒϥϦΛࠩ ͠ସ͑ΒΕΔɻ • ΄΅શͯͷϥϯλΠϜςετ͸͜ΕΛ෇͚ͯىಈ͞ΕΔɻ •

    ͜ͷػೳͷ͓ӄͰݹ͍OSͰ΋Swiftͷ։ൃ͕Ͱ͖ͯΔɻ 28
  29. ຊ୊ 29

  30. ConcurrencyͷόοΫσϓϩΠ 30

  31. ConcurrencyͷόοΫσϓϩΠ • جຊతʹadditiveͳมߋͳͷͰ͍͚ͦ͏ • ৽͍ؔ͠਺Λݹ͍ϥϯλΠϜʹσϓϩΠ͢Δඞཁ͕͋Δ 31

  32. Concurrencyʹඞཁͳ΋ͷ • libswiftCore.dylib ͷ௥ՃͷϥϯλΠϜؔ਺ • ؔ਺ܕϝλσʔλʹGlobalActorΛຒΊΔؔ܎Ͱඞཁ • libswift_Concurrency.dylibͷϥϯλΠϜ࣮૷ • λεΫͷεΠον

    • λεΫϩʔΧϧετϨʔδ • ͳͲͳͲ 32
  33. ConcurrencyόοΫσϓϩΠͷ೉ؔϙΠϯτ • ৽͍͠؀ڥͰOSಉ࣮ࠝ૷ʹ੾Γସ͑ΔͨΊͷαϯΫ͕ඞཁ • γϯϘϧ͕ॏෳ͠ͳ͍Α͏ʹϦωʔϜ͕ඞཁ • ίϯύΠϥ͕ు͘ίʔυ͸αϯΫΛࢀর͢Δඞཁ͋Γ • ޙड़ •

    OSಉࠝlibdispatchͷSwift޲͚ͷ৽ػೳʹґଘͯ͠ΔͷͰ ϑΥʔϧόοΫ͕ඞཁ 33
  34. ݱঢ়ͷεςʔλε 34

  35. πʔϧνΣΠϯͷϏϧυεΫϦϓτ όοΫσϓϩΠ༻ͷlibswift_Concurrency.dylib͕ϏϧυͰ ͖Δ • /usr/lib/swift-5.5/macosx/ libswift_Concurrency.dylibʹೖΔ • Ϗϧυ͕ग़དྷΔ͚ͩͰɺ͜Ε͚ͩͰ͸࢖͑ͳ͍ • Add

    an option to build the concurrency library for back deployment #39051 35
  36. ϥϯλΠϜͷςετ ݹ͍ϥϯλΠϜͱόοΫσϓϩΠϥΠϒϥϦͷ૊Έ߹Θ͕ͤς ετ͞ΕͯΔ • ͔͠͠΄ͱΜͲςετ͞Εͯͳ͍ • 60 / 63έʔε͕UNSUPPORTEDϚʔΫ෇͖ 36

  37. γϯϘϧॏෳ໰୊ ରԠࡁΈɻଟ෼ಈ͘ Back-deploy creation of global-actor-qualified function type metadata. #39280

    • ίϯύΠϥଆͱޓ׵ϥΠϒϥϦͷ࣮૷͕ऴΘͬͯΔ • ޓ׵ϥΠϒϥϦ libswiftCompatibilityConcurrency.a • طଘͷ࢓૊ΈͱͪΐͬͱࣅͯΔ 37
  38. // In "libswiftCore.dylib" in iOS 15 const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActor(...);

    // In "/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib" const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActorStandalone(...); // In "libswiftCompatibilityConcurrency.a" const FunctionTypeMetadata * swift_getFunctionTypeMetadataGlobalActorBackDeploy(...) { static BuilderFn builderFn; static dispatch_once_t builderToken; dispatch_once(&builderToken, ^{ // Prefer the function from the Swift runtime if it is available. builderFn = reinterpret_cast<BuilderFn>( dlsym(RTLD_DEFAULT, "swift_getFunctionTypeMetadataGlobalActor")); if (builderFn) return; builderFn = reinterpret_cast<BuilderFn>( dlsym(RTLD_DEFAULT, "swift_getFunctionTypeMetadataGlobalActorStandalone")); }); return builderFn(...); } https://github.com/apple/swift/blob/main/stdlib/public/BackDeployConcurrency/Metadata.cpp 38
  39. ίϯύΠϥυϥΠό ະ࣮૷ • ద੾ʹޓ׵ϥΠϒϥϦͱόοΫσϓϩΠϥΠϒϥϦΛϦϯΫ ͢Δ࣮૷͕ඞཁ 39

  40. ϥΠϒϥϦͷ഑෍ܗࣜ ະఆ • ݱঢ়ͷdylibΞϓϦຒࠐࣜͩͱγϯάϧόΠφϦʹͰ͖ͳ͍ 40

  41. Concurrency back-deployؔ࿈ϦϯΫ • Make the back-deployed concurrency dylibs depend only

    on what's available in older runtimes • Make swift_async_extendedFramePointerFlags = 0 in back- deployed configurations • Back-deploy creation of global-actor-qualified function type metadata. • Use private concurrent queues for back-deployed 41
  42. ΞϓϦʹউखʹಉࠝ͢Ε͹… ཧ࿦తʹ͸ಈ͘ɻ͕ɺ • ࠷৽ͷXcode͸ϥϯλΠϜಉࠝόϯυϧΛαϙʔτͯ͠ͳ ͍ɻ • SwiftͷoverlayΛશ෦ೖΕΔඞཁ͕͋ΔͷͰόΠφϦαΠζ૿ ͑Δ • Swift੡ͷOSϥΠϒϥϦ͕࢖͑ͳ͍

    like SwiftUI https://swift.org/blog/abi-stability-and-apple/ 42
  43. ·ͱΊ • ϥϯλΠϜ͸ඞͣޙํޓ׵ • લํޓ׵ੑ͸ϕετΤϑΥʔτ • ConcurrencyόοΫσϓϩΠ·Ͱ΋͏ͪΐͬͱʁ 43