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

Box式Type Erasureのmethod dispatch

Yuta Saito
October 29, 2018

Box式Type Erasureのmethod dispatch

わいわいswiftc #6

Yuta Saito

October 29, 2018
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. Boxࣜ Cat final class Cat: Animal { func play(with friend:

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

    friend) } callPlay(AnyAnimal(Cat()), friend: AnyAnimal(Cat())) 10
  5. ಈతʹܾ·ΔWitnessTable ྫ protocol Animal { func bark() } class Cat:

    Animal { func bark() {} } func callBark(_ animal: Animal) { animal.bark() } 13
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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