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

Box式Type Erasureのmethod dispatch

7a4968fbcd56e81f95a4f3c186141b52?s=47 Yuta Saito
October 29, 2018

Box式Type Erasureのmethod dispatch

わいわいswiftc #6

7a4968fbcd56e81f95a4f3c186141b52?s=128

Yuta Saito

October 29, 2018
Tweet

Transcript

  1. BoxࣜType Erasureͷ method dispatch Θ͍Θ͍swiftc #6 @kateinoigakukun 1

  2. iOSDCͷ෮श ίϯύΠϥ͔Βඥղ͘Swift method dispatch TL;DR • Swiftʹ͸ಈతσΟεύονͷํ͕ࣜ̎ͭ͋Δ • ϓϩτίϧͷWitnessTable •

    ΫϥεͷVTable 2
  3. ࠓ೔ͷ࿩ • BoxࣜType ErasureͷσΟεύον͕ Ͳ͏΍ͬͯಈ͍͍ͯΔͷ͔ 3

  4. Boxࣜ Type Erasure • SelfΛؚΉprotocol͸ΫϩʔδϟͰܕফڈ͢Δํ͕ࣜ࢖͑ͳ ͍ɻ • SelfΛম͖ͭͭܧঝͰܕফڈ͢Δํࣜɻ • ඪ४ϥΠϒϥϦͰ΋࢖ΘΕ͍ͯΔख๏

    • AnySequence • etc 4
  5. Boxࣜ Animal protocol Animal { func play(with friend: Self) }

    5
  6. Boxࣜ AnyAnimalbox class AnyAnimalBox { func play(with friend: AnyAnimalBox) {

    fatalError() } } 6
  7. Boxࣜ AnimalBox class AnimalBox<T: Animal>: AnyAnimalBox { let base: T

    init(base: T) { self.base = base } override func play(with friend: AnyAnimalBox) { base.play(with: (friend as! AnimalBox<T>).base) } } 7
  8. Boxࣜ AnyAnimal final class AnyAnimal: Animal { private let box:

    AnyAnimalBox init<T: Animal>(_ base: T) { box = AnimalBox<T>(base: base) } fileprivate init(box: AnyAnimalBox) { self.box = box } func play(with friend: AnyAnimal) { box.play(with: friend.box) } } 8
  9. Boxࣜ Cat final class Cat: Animal { func play(with friend:

    Cat) { print("play with \(friend)") } } 9
  10. Boxࣜ ݺͼग़͠ func callPlay(_ animal: AnyAnimal, friend: AnyAnimal) { animal.play(with:

    friend) } callPlay(AnyAnimal(Cat()), friend: AnyAnimal(Cat())) 10
  11. ؾʹͳΔϙΠϯτ • WitnessTableͱVTableͷ૊Έ߹Θͤ • ಈతʹܾ·ΔWitnessTable 11

  12. ಈతʹܾ·ΔWitnessTable AnyAnimal͸ܕύϥʹ<T: Animal>Λ࣋ͨͳ͍ͨΊɺ WitnessTableΛ੩తʹܾΊΒΕͳ͍ ࣅͨྫ: Existential Container 12

  13. ಈతʹܾ·ΔWitnessTable ྫ protocol Animal { func bark() } class Cat:

    Animal { func bark() {} } func callBark(_ animal: Animal) { animal.bark() } 13
  14. ϥϯλΠϜͷಈ͖Λ஌Γ͍ͨ • SIL͸Swiftͱಉ౳ͷܕγεςϜΛ͍࣋ͬͯΔͷͰɺ WitnessTableͷࢀরΛܕͰந৅ԽͰ͖Δɻ • witness_method %T, #Animal.play! • ࣮ࡍͷಈ͖Λ஌Δʹ͸

    LLVM IRΛಡΉ͔͠ͳ͍ 14
  15. Summary 1. AnyAnimal.allocating_init 2. AnimalBox Metadata accessor • ܕ৘ใʢϝλσʔλʣΛऔಘ͢Δ΍ͭ 3.

    AnimalBox type metadata completion function • δΣωϦοΫܕͷϝλσʔλΛิ׬͢Δ΍ͭ 4. swift_allocateGenericClassMetadata 5. AnimalBox type metadata completion function 15
  16. AnyAnimal.allocating_init • TܕͷϝλσʔλͱɺAnimalϓϩτίϧͷWitnessTable͕౉ͬͯ͘Δ • baseͷॳظԽΛ͢Δɻ class AnimalBox<T: Animal>: AnyAnimalBox {

    let base: T init(base: T) { self.base = base } ... } 16
  17. AnyAnimal.allocating_init LLVM IR define hidden swiftcc %T9AnyAnimalAAC* @"$S9AnyAnimalAACyABxcAA0B0Rzlufc"( %swift.opaque* noalias

    nocapture, %swift.type* %T, i8** %T.Animal, %T9AnyAnimalAAC* swiftself ) #0 { entry: ... %7 = bitcast i8* %6 to %swift.opaque* %8 = call swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMa"(i64 0, %swift.type* %T, i8** %T.Animal) #7 %9 = extractvalue %swift.metadata_response %8, 0 %13 = call swiftcc %T9AnyAnimal0B3BoxC* @"$S9AnyAnimal0B3BoxC4baseACyxGx_tcfC"( %swift.opaque* noalias nocapture %7, %swift.type* swiftself %9 ) %14 = bitcast %T9AnyAnimal0B3BoxC* %13 to %T9AnyAnimal0aB3BoxC* %15 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %1, i32 0, i32 1 store %T9AnyAnimal0aB3BoxC* %14, %T9AnyAnimal0aB3BoxC** %15, align 8 ... ret %T9AnyAnimalAAC* %1 } 17
  18. AnyAnimal.allocating_init LLVM IR define hidden swiftcc %T9AnyAnimalAAC* @"$S9AnyAnimalAACyABxcAA0B0Rzlufc"( %swift.opaque* noalias

    nocapture, %swift.type* %T, i8** %T.Animal, %T9AnyAnimalAAC* swiftself ) #0 { entry: ... %7 = bitcast i8* %6 to %swift.opaque* %8 = call swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMa"(i64 0, %swift.type* %T, i8** %T.Animal) #7 %9 = extractvalue %swift.metadata_response %8, 0 %13 = call swiftcc %T9AnyAnimal0B3BoxC* @"$S9AnyAnimal0B3BoxC4baseACyxGx_tcfC"( %swift.opaque* noalias nocapture %7, %swift.type* swiftself %9 ) %14 = bitcast %T9AnyAnimal0B3BoxC* %13 to %T9AnyAnimal0aB3BoxC* %15 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %1, i32 0, i32 1 store %T9AnyAnimal0aB3BoxC* %14, %T9AnyAnimal0aB3BoxC** %15, align 8 ... ret %T9AnyAnimalAAC* %1 } 17
  19. AnimalBox Metadata accessor LLVM IR define hidden swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMa"(i64,

    %swift.type*, i8**) #1 { entry: %generic.arguments = alloca { %swift.type*, i8** }, align 8 %3 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %4 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 0 store %swift.type* %1, %swift.type** %4, align 8 %5 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 1 store i8** %2, i8*** %5, align 8 %6 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %7 = call swiftcc %swift.metadata_response @swift_getGenericMetadata( i64 %0, i8* %6, %swift.type_descriptor* @"$S9AnyAnimal0B3BoxCMn" ) %9 = extractvalue %swift.metadata_response %7, 0 %10 = extractvalue %swift.metadata_response %7, 1 %11 = insertvalue %swift.metadata_response undef, %swift.type* %9, 0 %12 = insertvalue %swift.metadata_response %11, i64 %10, 1 ret %swift.metadata_response %12 } 18
  20. AnimalBox Metadata accessor LLVM IR define hidden swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMa"(i64,

    %swift.type*, i8**) #1 { entry: %generic.arguments = alloca { %swift.type*, i8** }, align 8 %3 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %4 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 0 store %swift.type* %1, %swift.type** %4, align 8 %5 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 1 store i8** %2, i8*** %5, align 8 %6 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %7 = call swiftcc %swift.metadata_response @swift_getGenericMetadata( i64 %0, i8* %6, %swift.type_descriptor* @"$S9AnyAnimal0B3BoxCMn" ) %9 = extractvalue %swift.metadata_response %7, 0 %10 = extractvalue %swift.metadata_response %7, 1 %11 = insertvalue %swift.metadata_response undef, %swift.type* %9, 0 %12 = insertvalue %swift.metadata_response %11, i64 %10, 1 ret %swift.metadata_response %12 } 18
  21. AnimalBox Metadata accessor LLVM IR define hidden swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMa"(i64,

    %swift.type*, i8**) #1 { entry: %generic.arguments = alloca { %swift.type*, i8** }, align 8 %3 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %4 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 0 store %swift.type* %1, %swift.type** %4, align 8 %5 = getelementptr inbounds { %swift.type*, i8** }, { %swift.type*, i8** }* %generic.arguments, i32 0, i32 1 store i8** %2, i8*** %5, align 8 %6 = bitcast { %swift.type*, i8** }* %generic.arguments to i8* %7 = call swiftcc %swift.metadata_response @swift_getGenericMetadata( i64 %0, i8* %6, %swift.type_descriptor* @"$S9AnyAnimal0B3BoxCMn" ) %9 = extractvalue %swift.metadata_response %7, 0 %10 = extractvalue %swift.metadata_response %7, 1 %11 = insertvalue %swift.metadata_response undef, %swift.type* %9, 0 %12 = insertvalue %swift.metadata_response %11, i64 %10, 1 ret %swift.metadata_response %12 } 18
  22. swift_allocateGenericClassMetadata C++ ClassMetadata * swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description, const void *arguments,

    const GenericClassMetadataPattern *pattern){ auto &generics = description->getFullGenericContextHeader(); ... auto metadata = reinterpret_cast<ClassMetadata *>(addressPoint); ... // Copy the generic arguments into place. installGenericArguments(metadata, description, arguments); return metadata; } 19
  23. swift_allocateGenericClassMetadata C++ ClassMetadata * swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description, const void *arguments,

    const GenericClassMetadataPattern *pattern){ auto &generics = description->getFullGenericContextHeader(); ... auto metadata = reinterpret_cast<ClassMetadata *>(addressPoint); ... // Copy the generic arguments into place. installGenericArguments(metadata, description, arguments); return metadata; } 19
  24. installGenericArguments C++ static void installGenericArguments(Metadata *metadata, const TypeContextDescriptor *description, const

    void *arguments) { auto &generics = description->getFullGenericContextHeader(); // If we ever have parameter packs, we may need to do more than just // copy here. memcpy(reinterpret_cast<const void **>(metadata) + description->getGenericArgumentOffset(), reinterpret_cast<const void * const *>(arguments), generics.Base.getNumArguments() * sizeof(void*)); } 20
  25. AnimalBox type metadata completion function LLVM IR define internal swiftcc

    %swift.metadata_response @"$S9AnyAnimal0B3BoxCMr"( %swift.type* %"AnimalBox<T>", i8*, i8** ) #0 { entry: ... %23 = bitcast %swift.type* %"AnimalBox<T>" to i8** %24 = getelementptr inbounds i8*, i8** %23, i64 10 store i8* bitcast ( void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0B3BoxC*)* @"$S9AnyAnimal0B3BoxC4play4withyAA0abC0C_tF" to i8* ), i8** %24, align 8 %25 = bitcast %swift.type* %"AnimalBox<T>" to i8** %26 = getelementptr inbounds i8*, i8** %25, i64 11 store i8* bitcast ( %T9AnyAnimal0B3BoxC* (%T9AnyAnimal0B3BoxC*)* @"$S9AnyAnimal0B3BoxCACyxGycfc" to i8* ), i8** %26, align 8 ... } 21
  26. AnyAnimal.play LLVM IR define hidden swiftcc void @"$S9AnyAnimalAAC4play4withyAB_tF"( %T9AnyAnimalAAC*, %T9AnyAnimalAAC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %1, i32 0, i32 1 %3 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %2, align 8 %4 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %0, i32 0, i32 1 %5 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %4, align 8 %6 = getelementptr inbounds %T9AnyAnimal0aB3BoxC, %T9AnyAnimal0aB3BoxC* %3, i32 0, i32 0, i32 0 %7 = load %swift.type*, %swift.type** %6, align 8 %8 = bitcast %swift.type* %7 to void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9 = getelementptr inbounds ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %8, i64 10 %10 = load ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9, align 8, !invariant.load !50 call swiftcc void %10(%T9AnyAnimal0aB3BoxC* %5, %T9AnyAnimal0aB3BoxC* swiftself %3) ret void } 22
  27. AnyAnimal.play LLVM IR define hidden swiftcc void @"$S9AnyAnimalAAC4play4withyAB_tF"( %T9AnyAnimalAAC*, %T9AnyAnimalAAC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %1, i32 0, i32 1 %3 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %2, align 8 %4 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %0, i32 0, i32 1 %5 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %4, align 8 %6 = getelementptr inbounds %T9AnyAnimal0aB3BoxC, %T9AnyAnimal0aB3BoxC* %3, i32 0, i32 0, i32 0 %7 = load %swift.type*, %swift.type** %6, align 8 %8 = bitcast %swift.type* %7 to void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9 = getelementptr inbounds ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %8, i64 10 %10 = load ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9, align 8, !invariant.load !50 call swiftcc void %10(%T9AnyAnimal0aB3BoxC* %5, %T9AnyAnimal0aB3BoxC* swiftself %3) ret void } 22
  28. AnyAnimal.play LLVM IR define hidden swiftcc void @"$S9AnyAnimalAAC4play4withyAB_tF"( %T9AnyAnimalAAC*, %T9AnyAnimalAAC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %1, i32 0, i32 1 %3 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %2, align 8 %4 = getelementptr inbounds %T9AnyAnimalAAC, %T9AnyAnimalAAC* %0, i32 0, i32 1 %5 = load %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC** %4, align 8 %6 = getelementptr inbounds %T9AnyAnimal0aB3BoxC, %T9AnyAnimal0aB3BoxC* %3, i32 0, i32 0, i32 0 %7 = load %swift.type*, %swift.type** %6, align 8 %8 = bitcast %swift.type* %7 to void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9 = getelementptr inbounds ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %8, i64 10 %10 = load ..., void (%T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0aB3BoxC*)** %9, align 8, !invariant.load !50 call swiftcc void %10(%T9AnyAnimal0aB3BoxC* %5, %T9AnyAnimal0aB3BoxC* swiftself %3) ret void } 22
  29. AnimalBox.play LLVM IR define hidden swiftcc void @"$S9AnyAnimal0B3BoxC4play4withyAA0abC0C_tF"( %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0B3BoxC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimal0B3BoxC, %T9AnyAnimal0B3BoxC* %1, i32 0, i32 0, i32 0 %3 = load %swift.type*, %swift.type** %2, align 8 ... %22 = bitcast %swift.type* %3 to i8*** %23 = getelementptr inbounds i8**, i8*** %22, i64 13 %T.Animal = load i8**, i8*** %23, align 8, !invariant.load !50 ... %39 = getelementptr inbounds i8*, i8** %T.Animal, i32 1 %40 = load i8*, i8** %39, align 8, !invariant.load !50 %41 = bitcast i8* %40 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* call swiftcc void %41( %swift.opaque* noalias nocapture %11, %swift.opaque* noalias nocapture swiftself %.base, %swift.type* %T, i8** %T.Animal ) ... ret void } 23
  30. AnimalBox.play LLVM IR define hidden swiftcc void @"$S9AnyAnimal0B3BoxC4play4withyAA0abC0C_tF"( %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0B3BoxC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimal0B3BoxC, %T9AnyAnimal0B3BoxC* %1, i32 0, i32 0, i32 0 %3 = load %swift.type*, %swift.type** %2, align 8 ... %22 = bitcast %swift.type* %3 to i8*** %23 = getelementptr inbounds i8**, i8*** %22, i64 13 %T.Animal = load i8**, i8*** %23, align 8, !invariant.load !50 ... %39 = getelementptr inbounds i8*, i8** %T.Animal, i32 1 %40 = load i8*, i8** %39, align 8, !invariant.load !50 %41 = bitcast i8* %40 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* call swiftcc void %41( %swift.opaque* noalias nocapture %11, %swift.opaque* noalias nocapture swiftself %.base, %swift.type* %T, i8** %T.Animal ) ... ret void } 23
  31. AnimalBox.play LLVM IR define hidden swiftcc void @"$S9AnyAnimal0B3BoxC4play4withyAA0abC0C_tF"( %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0B3BoxC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimal0B3BoxC, %T9AnyAnimal0B3BoxC* %1, i32 0, i32 0, i32 0 %3 = load %swift.type*, %swift.type** %2, align 8 ... %22 = bitcast %swift.type* %3 to i8*** %23 = getelementptr inbounds i8**, i8*** %22, i64 13 %T.Animal = load i8**, i8*** %23, align 8, !invariant.load !50 ... %39 = getelementptr inbounds i8*, i8** %T.Animal, i32 1 %40 = load i8*, i8** %39, align 8, !invariant.load !50 %41 = bitcast i8* %40 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* call swiftcc void %41( %swift.opaque* noalias nocapture %11, %swift.opaque* noalias nocapture swiftself %.base, %swift.type* %T, i8** %T.Animal ) ... ret void } 23
  32. AnimalBox.play LLVM IR define hidden swiftcc void @"$S9AnyAnimal0B3BoxC4play4withyAA0abC0C_tF"( %T9AnyAnimal0aB3BoxC*, %T9AnyAnimal0B3BoxC*

    swiftself ) #0 { entry: %2 = getelementptr inbounds %T9AnyAnimal0B3BoxC, %T9AnyAnimal0B3BoxC* %1, i32 0, i32 0, i32 0 %3 = load %swift.type*, %swift.type** %2, align 8 ... %22 = bitcast %swift.type* %3 to i8*** %23 = getelementptr inbounds i8**, i8*** %22, i64 13 %T.Animal = load i8**, i8*** %23, align 8, !invariant.load !50 ... %39 = getelementptr inbounds i8*, i8** %T.Animal, i32 1 %40 = load i8*, i8** %39, align 8, !invariant.load !50 %41 = bitcast i8* %40 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* call swiftcc void %41( %swift.opaque* noalias nocapture %11, %swift.opaque* noalias nocapture swiftself %.base, %swift.type* %T, i8** %T.Animal ) ... ret void } 23
  33. Cat.play witness method define internal swiftcc void @"$S9AnyAnimalAACAA0B0A2aCP4play4withyx_tFTW"( %T9AnyAnimalAAC** noalias

    nocapture dereferenceable(8), %T9AnyAnimalAAC** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable ) #0 { entry: %2 = load %T9AnyAnimalAAC*, %T9AnyAnimalAAC** %0, align 8 %3 = load %T9AnyAnimalAAC*, %T9AnyAnimalAAC** %1, align 8 call swiftcc void @"$S9AnyAnimalAAC4play4withyAB_tF"(%T9AnyAnimalAAC* %2, %T9AnyAnimalAAC* swiftself %3) #10 ret void } 24
  34. ·ͱΊ init࣌ • WitnessTableͱܕύϥͷϝλσʔλΛϝλσʔλʹম͖ࠐΉ • Type metadata completion Ͱ VTableΛ࡞Δ

    25
  35. ·ͱΊ σΟεύον 1. AnyAnimal.play 2. AnyAnimalBoxܕͷVTable͔ΒAnimalBoxͷplayΛݺͼग़͠ 3. AnimalBoxͷϝλσʔλ͔ΒܕύϥͷWitnessTableऔΓग़ͯ͠ witness methodΛݺͼग़͠ɻ

    4. baseͷplayϝιουΛݺͼग़͢ɻ 5. base͕AnyAnimalͷ৔߹ɺ1ʹ໭Δ 26