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

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

Yuta Saito
September 24, 2021

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

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

Yuta Saito

September 24, 2021
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  6. ϥϯλΠϜͷ໾ׂ
    • Swiftͷ࣮ߦʹ͸ϥϯλΠϜϥΠϒϥϦ͕ඞཁ
    • libswiftCore.dylib
    • ݴޠͷ࣮ߦ࣌ػೳΛఏڙ
    • ಈతΩϟετ
    • ARC
    • etc ...
    6

    View Slide

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

    View Slide

  8. SwiftͷABI Stability
    ίϯύΠϥͷੜ੒όΠφϦɺϥϯλΠϜͷABIʹ͍ͭͯ
    ޓ׵ੑΛอͭ໿ଋ
    • લํ/ޙํ ͲͪΒʹ΋ޓ׵
    • ޙํͷํ͕େࣄɻલํ͸࠷ѱ෦෼తͰ΋OK
    • ABI Stability Manifestʹৄ͍͠ن໿͕͋Δ
    https://github.com/apple/swift/blob/main/docs/ABIStabilityManifesto.md 8

    View Slide

  9. ABI Stability͕Մೳʹ͢Δ͜ͱ

    • Swift 5.0ͰίϯύΠϧͨ͠ϥΠϒϥϦ͕ɺ
    Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦͰ࢖͑Δɻ
    • Swift 5.0ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ
    Swift 5.1ͷϥϯλΠϜͰಈ͘ɻ
    • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦ͕ɺ
    Swift 5.0ͷϥϯλΠϜͰಈ͘ɻ
    9

    View Slide

  10. ABI Stabilizeલ (~ Swift 5.0)
    • ֤ΞϓϦ͕ϥϯλΠϜϥΠϒϥϦΛಉࠝ
    • ΞϓϦͱϥϯλΠϜͷݴޠόʔδϣϯ͕ৗʹҰக
    ./My.app
    ├── Frameworks
    │ └── libswiftCore.dylib
    ├── Info.plist
    ├── My
    └── _CodeSignature
    10

    View Slide

  11. ABI Stabilizeલ (Swift 5.0 ~)
    • iOS 13ɺmacOS 10.14.4 ͔ΒOSࣗମʹಉࠝ
    • ϥΠϒϥϦΛల։͢ΔϝϞϦΛΞϓϦؒͰڞ༗
    • ΞϓϦͷόϯυϧαΠζ΋ݮͬͯخ͍͠
    • ͕ɺϥϯλΠϜͷόʔδϣϯ͕OS͝ͱʹݻఆ͞Εͯ͠·ͬͨ
    11

    View Slide

  12. ϥϯλΠϜ͕OSʹೖΔ͜ͱͰى͜Δ໰୊
    ΞϓϦ͕࢖͏ݴޠόʔδϣϯͱϥϯλΠϜόʔδϣϯ͕ඞͣ͠
    ΋Ұக͠ͳ͍

    • Swift 5.0ͰίϯύΠϧͨ͠ΞϓϦΛɺ
    Swift 5.1ͷϥϯλΠϜͰಈ͔͢ɻ -> ϥϯλΠϜͷޙํޓ׵ੑ
    • Swift 5.2ͰίϯύΠϧͨ͠ΞϓϦΛɺ
    Swift 5.0ͷϥϯλΠϜͰಈ͔͢ɻ -> ϥϯλΠϜͷલํޓ׵ੑ
    12

    View Slide

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

    View Slide

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

    View Slide

  15. ϥϯλΠϜͷલํޓ׵ੑ
    ৽͍͠SwiftΞϓϦΛݹ͍SwiftϥϯλΠϜͰಈ͔͢
    • ΞϓϦ͸ݹ͍ϥϯλΠϜ͕஌Βͳ͍ػೳ/ڍಈΛཁٻ͢Δ
    • όοΫσϓϩΠͷग़൪
    15

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  20. libswiftCompatibilityX.a ͷਖ਼ମ
    • όʔδϣϯXͷϥϯλΠϜʹ଍Γͳ͍ɺݱࡏͷόʔδϣϯͷػ
    ೳΛ࣮૷
    • ϑοΫηΫγϣϯʢe.g. __swift51_hooksʣʹΦʔόʔϥΠ
    υ͢Δؔ਺ϦετΛೖΕΔ
    20

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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(
    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

    View Slide

  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

    View Slide

  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

    View Slide

  27. ίϯύΠϥ։ൃ؀ڥͰͷϋοΫ
    • όΠφϦ͸OSಉࠝ(/usr/lib/swift/libswiftCore.dylib)ΛϦϯΫ
    ͯ͠Δ
    • ։ൃத͸ίϯύΠϥόʔδϣϯͱҰகͨ͠ϥϯλΠϜ͕खݩ
    ʹ͋Δ
    • ։ൃத͸OSಉࠝ͡Όͳ͍ϥϯλΠϜΛ࢖͍͍ͨ
    27

    View Slide

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

    View Slide

  29. ຊ୊
    29

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  33. ConcurrencyόοΫσϓϩΠͷ೉ؔϙΠϯτ
    • ৽͍͠؀ڥͰOSಉ࣮ࠝ૷ʹ੾Γସ͑ΔͨΊͷαϯΫ͕ඞཁ
    • γϯϘϧ͕ॏෳ͠ͳ͍Α͏ʹϦωʔϜ͕ඞཁ
    • ίϯύΠϥ͕ు͘ίʔυ͸αϯΫΛࢀর͢Δඞཁ͋Γ
    • ޙड़
    • OSಉࠝlibdispatchͷSwift޲͚ͷ৽ػೳʹґଘͯ͠ΔͷͰ
    ϑΥʔϧόοΫ͕ඞཁ
    33

    View Slide

  34. ݱঢ়ͷεςʔλε
    34

    View Slide

  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

    View Slide

  36. ϥϯλΠϜͷςετ
    ݹ͍ϥϯλΠϜͱόοΫσϓϩΠϥΠϒϥϦͷ૊Έ߹Θ͕ͤς
    ετ͞ΕͯΔ
    • ͔͠͠΄ͱΜͲςετ͞Εͯͳ͍
    • 60 / 63έʔε͕UNSUPPORTEDϚʔΫ෇͖
    36

    View Slide

  37. γϯϘϧॏෳ໰୊
    ରԠࡁΈɻଟ෼ಈ͘
    Back-deploy creation of global-actor-qualified function type
    metadata. #39280
    • ίϯύΠϥଆͱޓ׵ϥΠϒϥϦͷ࣮૷͕ऴΘͬͯΔ
    • ޓ׵ϥΠϒϥϦ libswiftCompatibilityConcurrency.a
    • طଘͷ࢓૊ΈͱͪΐͬͱࣅͯΔ
    37

    View Slide

  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(
    dlsym(RTLD_DEFAULT, "swift_getFunctionTypeMetadataGlobalActor"));
    if (builderFn)
    return;
    builderFn = reinterpret_cast(
    dlsym(RTLD_DEFAULT,
    "swift_getFunctionTypeMetadataGlobalActorStandalone"));
    });
    return builderFn(...);
    }
    https://github.com/apple/swift/blob/main/stdlib/public/BackDeployConcurrency/Metadata.cpp 38

    View Slide

  39. ίϯύΠϥυϥΠό
    ະ࣮૷
    • ద੾ʹޓ׵ϥΠϒϥϦͱόοΫσϓϩΠϥΠϒϥϦΛϦϯΫ
    ͢Δ࣮૷͕ඞཁ
    39

    View Slide

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

    View Slide

  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

    View Slide

  42. ΞϓϦʹউखʹಉࠝ͢Ε͹…
    ཧ࿦తʹ͸ಈ͘ɻ͕ɺ
    • ࠷৽ͷXcode͸ϥϯλΠϜಉࠝόϯυϧΛαϙʔτͯ͠ͳ
    ͍ɻ
    • SwiftͷoverlayΛશ෦ೖΕΔඞཁ͕͋ΔͷͰόΠφϦαΠζ૿
    ͑Δ
    • Swift੡ͷOSϥΠϒϥϦ͕࢖͑ͳ͍ like SwiftUI
    https://swift.org/blog/abi-stability-and-apple/ 42

    View Slide

  43. ·ͱΊ
    • ϥϯλΠϜ͸ඞͣޙํޓ׵
    • લํޓ׵ੑ͸ϕετΤϑΥʔτ
    • ConcurrencyόοΫσϓϩΠ·Ͱ΋͏ͪΐͬͱʁ
    43

    View Slide