Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

Boxࣜ Animal protocol Animal { func play(with friend: Self) } 5

Slide 6

Slide 6 text

Boxࣜ AnyAnimalbox class AnyAnimalBox { func play(with friend: AnyAnimalBox) { fatalError() } } 6

Slide 7

Slide 7 text

Boxࣜ AnimalBox class AnimalBox: AnyAnimalBox { let base: T init(base: T) { self.base = base } override func play(with friend: AnyAnimalBox) { base.play(with: (friend as! AnimalBox).base) } } 7

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Boxࣜ Cat final class Cat: Animal { func play(with friend: Cat) { print("play with \(friend)") } } 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

ؾʹͳΔϙΠϯτ • WitnessTableͱVTableͷ૊Έ߹Θͤ • ಈతʹܾ·ΔWitnessTable 11

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

ϥϯλΠϜͷಈ͖Λ஌Γ͍ͨ • SIL͸Swiftͱಉ౳ͷܕγεςϜΛ͍࣋ͬͯΔͷͰɺ WitnessTableͷࢀরΛܕͰந৅ԽͰ͖Δɻ • witness_method %T, #Animal.play! • ࣮ࡍͷಈ͖Λ஌Δʹ͸ LLVM IRΛಡΉ͔͠ͳ͍ 14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

AnyAnimal.allocating_init • TܕͷϝλσʔλͱɺAnimalϓϩτίϧͷWitnessTable͕౉ͬͯ͘Δ • baseͷॳظԽΛ͢Δɻ class AnimalBox: AnyAnimalBox { let base: T init(base: T) { self.base = base } ... } 16

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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(metadata) + description->getGenericArgumentOffset(), reinterpret_cast(arguments), generics.Base.getNumArguments() * sizeof(void*)); } 20

Slide 25

Slide 25 text

AnimalBox type metadata completion function LLVM IR define internal swiftcc %swift.metadata_response @"$S9AnyAnimal0B3BoxCMr"( %swift.type* %"AnimalBox", i8*, i8** ) #0 { entry: ... %23 = bitcast %swift.type* %"AnimalBox" 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" to i8** %26 = getelementptr inbounds i8*, i8** %25, i64 11 store i8* bitcast ( %T9AnyAnimal0B3BoxC* (%T9AnyAnimal0B3BoxC*)* @"$S9AnyAnimal0B3BoxCACyxGycfc" to i8* ), i8** %26, align 8 ... } 21

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

·ͱΊ init࣌ • WitnessTableͱܕύϥͷϝλσʔλΛϝλσʔλʹম͖ࠐΉ • Type metadata completion Ͱ VTableΛ࡞Δ 25

Slide 35

Slide 35 text

·ͱΊ σΟεύον 1. AnyAnimal.play 2. AnyAnimalBoxܕͷVTable͔ΒAnimalBoxͷplayΛݺͼग़͠ 3. AnimalBoxͷϝλσʔλ͔ΒܕύϥͷWitnessTableऔΓग़ͯ͠ witness methodΛݺͼग़͠ɻ 4. baseͷplayϝιουΛݺͼग़͢ɻ 5. base͕AnyAnimalͷ৔߹ɺ1ʹ໭Δ 26