Slide 1

Slide 1 text

ίϯύΠϥ͔Βඥղ͘ 4XJGUNFUIPEEJTQBUDI !LBUFJOPJHBLVLVO

Slide 2

Slide 2 text

ࣗݾ঺հ w !LBUFJOPJHBLVLVO w ૣҴాେֶߴ౳ֶӃ̏೥

Slide 3

Slide 3 text

͍͖ͳΓͰ͕͢

Slide 4

Slide 4 text

ΫΠζͰ͢

Slide 5

Slide 5 text

class Cat { func bark() -> String { return "ʹΌΜ" } } class Dog { func bark() -> String { return "ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) 2Կ͕ग़ྗ͞ΕΔͰ͠ΐ͏ʁ ʹΌΜPSΘΜ

Slide 6

Slide 6 text

class Cat { func bark() -> String { return "ʹΌΜ" } } class Dog { func bark() -> String { return "ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) 2Կ͕ग़ྗ͞ΕΔͰ͠ΐ͏ʁ "ΘΜ

Slide 7

Slide 7 text

ʮΘΜʯ

Slide 8

Slide 8 text

ࠓ೔࿩͢͜ͱ w .FUIPE%JTQBUDIͷ࢓૊Έ w ࠷దԽͷ࢓૊Έ w ύϑΥʔϚϯε

Slide 9

Slide 9 text

2.FUIPEEJTQBUDIͱ͸ʁ

Slide 10

Slide 10 text

2.FUIPEEJTQBUDIͱ͸ʁ "ϝιου͕ݺͼग़͞ΕΔ࣌ʹɺ
 ࣮ࡍʹͲͷϝιουΛ࣮ߦ͢Δ͔ΛܾΊΔػߏ

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

class Animal { func bark() { print("ΞχϚϧͰ͢") } } class Cat: Animal { override func bark() { print("ʹΌΜ") } } func callAnimalBark(_ animal: Animal) { animal.bark() }

Slide 13

Slide 13 text

class Animal { func bark() { print("ΞχϚϧͰ͢") } } class Cat: Animal { override func bark() { print("ʹΌΜ") } } func callAnimalBark(_ animal: Animal) { animal.bark() // ΞχϚϧͰ͢ or ʹΌΜ }

Slide 14

Slide 14 text

class Animal { func bark() { print("ΞχϚϧͰ͢") } } class Cat: Animal { override func bark() { print("ʹΌΜ") } } func callAnimalBark(_ animal: Animal) { animal.bark() // ΞχϚϧͰ͢ or ʹΌΜ } ࣮ߦ͞ΕΔϝιου͸Ͳͬͪʁʁ

Slide 15

Slide 15 text

.FUIPE%JTQBUDIͷύλʔϯ w 4UBUJD%JTQBUDI w ݺͼग़͢ϝιουΛίϯύΠϧ࣌ʹܾΊΔ w %ZOBNJD%JTQBUDI w ݺͼग़͢ϝιουΛ࣮ߦ࣌ʹܾΊΔ

Slide 16

Slide 16 text

4UBUJD%JTQBUDI w ؔ਺ w ஋ܕͷϝιου w FYUFOTJPOʹॻ͍ͨϝιου w pOBMͳϝιου struct S { func foo() {} } let s = S() s.foo()

Slide 17

Slide 17 text

4UBUJD%JTQBUDI struct S { func foo() {} } let s = S() s.foo() ಉ͡γάωνϟͷϝιου͕ଘࡏ͠ͳ͍ w ؔ਺ w ஋ܕͷϝιου w FYUFOTJPOʹॻ͍ͨϝιου w pOBMͳϝιου

Slide 18

Slide 18 text

%ZOBNJD%JTQBUDI w $MBTTͷϝιου w 1SPUPDPMͷϝιου protocol Animal { func foo() } struct Cat: Animal { func foo() {} } func callFoo(_ animal: T) { animal.foo() }

Slide 19

Slide 19 text

w $MBTTͷϝιουΦʔόʔϥΠυ w 1SPUPDPMͷϝιουෳ਺ͷܕ͕४ڌ %ZOBNJD%JTQBUDI protocol Animal { func foo() } struct Cat: Animal { func foo() {} } func callFoo(_ animal: T) { animal.foo() } ಉ͡γάωνϟͷϝιου͕ෳ਺ଘࡏ͢Δ

Slide 20

Slide 20 text

.FUIPE%JTQBUDIͷύλʔϯ w 4UBUJD%JTQBUDI w ݺͼग़͢ϝιουΛίϯύΠϧ࣌ʹܾΊΔ w %ZOBNJD%JTQBUDI w ݺͼग़͢ϝιουΛ࣮ߦ࣌ʹܾΊΔ

Slide 21

Slide 21 text

.FUIPE%JTQBUDIͷύλʔϯ w 4UBUJD%JTQBUDI w ݺͼग़͢ϝιουΛίϯύΠϧ࣌ʹܾΊΔ w %ZOBNJD%JTQBUDI w ݺͼग़͢ϝιουΛ࣮ߦ࣌ʹܾΊΔ w 75BCMF w 8JUOFTT5BCMF

Slide 22

Slide 22 text

75BCMF w Ծ૝ؔ਺ςʔϒϧ͔ΒϝιουΛ୳ࡧ͢Δ%JTQBUDIํࣜ w ΫϥεͷϝιουΛݺͼग़࣌͢ʹ࢖͏ w ΠϯελϯεͷϝλσʔλʹຒΊࠐ·ΕΔ

Slide 23

Slide 23 text

func Animal.bark() *Animal.bark 75BCMFGPS"OJNBM class Animal { func bark() {} }

Slide 24

Slide 24 text

func Animal.bark() *Animal.bark 75BCMFGPS$BU *Animal.bark 75BCMFGPS"OJNBM class Animal { func bark() {} } class Cat: Animal { }

Slide 25

Slide 25 text

func Cat.foo() func Animal.bark() *Animal.bark *Animal.bark *Cat.foo 75BCMFGPS"OJNBM 75BCMFGPS$BU class Animal { func bark() {} } class Cat: Animal { func foo() {} }

Slide 26

Slide 26 text

class Animal { func bark() {} } class Cat: Animal { override func bark() {} func foo() {} } 75BCMFGPS$BU func Animal.bark() 75BCMFGPS"OJNBM *Animal.bark *Animal.bark *Cat.foo func Cat.bark() func Cat.foo()

Slide 27

Slide 27 text

8JUOFTT5BCMF w Ծ૝ؔ਺ςʔϒϧ͔ΒϝιουΛ୳ࡧ͢Δ%JTQBUDIํࣜ w ϓϩτίϧͷϝιουΛݺͼग़࣌͢ʹ࢖͏ w ϓϩτίϧ΁ͷ४ڌ͝ͱʹఆٛ͞ΕΔ

Slide 28

Slide 28 text

protocol Animal { func bark() }

Slide 29

Slide 29 text

protocol Animal { func bark() } struct Dog: Animal { func bark() {} } 8JUOFTT5BCMFGPS"OJNBM JODPOGPSNBODF%PH *Animal.bark func Animal.bark(dog) { Dog.bark(dog) } 8JUOFTTNFUIPEGPS"OJNBM JODPOGPSNBODF%PH

Slide 30

Slide 30 text

ʮΘΜʯ໰୊

Slide 31

Slide 31 text

class Cat { func bark() -> String { return "ʹΌΜ" } } class Dog { func bark() -> String { return “ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) ϝϞϦϨΠΞ΢τ͸มߋ͞Εͳ͍ ࢀর͢ΔVTable΋มΘΒͳ͍ Catͷςʔϒϧ͕ࢀর͞ΕΔ ʮʹΌΜʯ͕ग़ྗ͞ΕΔ͸ͣʂ

Slide 32

Slide 32 text

͔͠͠ɺ

Slide 33

Slide 33 text

class Cat { func bark() -> String { return "ʹΌΜ" } } class Dog { func bark() -> String { return "ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) // ΘΜ ʮΘΜʯ

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

࠷దԽΛΦϑʹͯ͠ΈΔ

Slide 36

Slide 36 text

$ swiftc -frontend -c -primary-file animal.swift $ swiftc animal.o $ ./animal ʹΌΜ ʮʹΌΜʯ

Slide 37

Slide 37 text

࠷దԽͷաఔʹԿ͔͋Γͦ͏

Slide 38

Slide 38 text

%FWJSUVBMJ[F

Slide 39

Slide 39 text

%FWJSUVBMJ[F w 4*-0QUJNJ[FSͷ࠷దԽύε w %ZOBNJD%JTQBUDIΛ4UBUJD%JTQBUDIʹ࠷దԽ͢Δ w ίϯύΠϧ࣌ͷܕ৘ใ͔ΒϝιουΛ̍ͭʹܾΊΔ

Slide 40

Slide 40 text

75BCMFͷ࠷దԽ

Slide 41

Slide 41 text

USZ%FWJSUVBMJ[F"QQMZ auto &M = FAS.getModule(); auto Instance = stripUpCasts(CMI->getOperand()); auto ClassType = Instance->getType(); ... if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE, true /*isEffectivelyFinalMethod*/); if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE); if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) { if (ExactTy == CMI->getOperand()->getType()) return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), ORE); } MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 42

Slide 42 text

USZ%FWJSUVBMJ[F"QQMZ auto &M = FAS.getModule(); auto Instance = stripUpCasts(CMI->getOperand()); auto ClassType = Instance->getType(); ... if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE, true /*isEffectivelyFinalMethod*/); if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE); if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) { if (ExactTy == CMI->getOperand()->getType()) return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), ORE); } Πϯελϯεͷ࣮ߦ࣌ͷܕ͕੩తʹܾఆͰ͖Δύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 43

Slide 43 text

%FWJSUVBMJ[FGPS75BCMF class Animal { func bark() {} } class Cat: Animal { override func bark() {} } let animal: Animal = Cat() // ΠχγϟϥΠβ͔Β࡞ͬͯΔͷͰCatܕ animal.bark() Πϯελϯεͷ࣮ߦ࣌ͷܕ͕੩తʹܾఆͰ͖Δύλʔϯ

Slide 44

Slide 44 text

USZ%FWJSUVBMJ[F"QQMZ auto &M = FAS.getModule(); auto Instance = stripUpCasts(CMI->getOperand()); auto ClassType = Instance->getType(); ... if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE, true /*isEffectivelyFinalMethod*/); if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) return tryDevirtualizeClassMethod(FAS, Instance, ORE); if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CMI->getModule(), CHA)) { if (ExactTy == CMI->getOperand()->getType()) return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), ORE); } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 45

Slide 45 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { if (CD && CD->isFinal()) return true; const DeclContext *DC = AI.getModule().getAssociatedContext(); auto *CMI = cast(AI.getCallee()); if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember())) return false; auto *Method = CMI->getMember().getAbstractFunctionDecl(); if (!Method->isOverridden()) return true; ... return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 46

Slide 46 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { if (CD && CD->isFinal()) return true; const DeclContext *DC = AI.getModule().getAssociatedContext(); auto *CMI = cast(AI.getCallee()); if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember())) return false; auto *Method = CMI->getMember().getAbstractFunctionDecl(); if (!Method->isOverridden()) return true; ... return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 47

Slide 47 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { if (CD && CD->isFinal()) return true; const DeclContext *DC = AI.getModule().getAssociatedContext(); auto *CMI = cast(AI.getCallee()); if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember())) return false; auto *Method = CMI->getMember().getAbstractFunctionDecl(); if (!Method->isOverridden()) return true; ... return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 48

Slide 48 text

DBMMFFT"SF4UBUJDBMMZ,OPXBCMF bool swift::calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl) { ... switch (AFD->getEffectiveAccess()) { case AccessLevel::Open: return false; case AccessLevel::Public: if (isa(AFD)) { auto *ND = AFD->getDeclContext()->getSelfNominalTypeDecl(); if (ND->getEffectiveAccess() == AccessLevel::Open) return false; } case AccessLevel::Internal: return M.isWholeModule(); case AccessLevel::FilePrivate: case AccessLevel::Private: return true; } } ϝιουΛ੩తʹܾఆͰ͖Δύλʔϯ MJC4*-0QUJNJ[FS6UJMT-PDBMDQQ

Slide 49

Slide 49 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { if (CD && CD->isFinal()) return true; const DeclContext *DC = AI.getModule().getAssociatedContext(); auto *CMI = cast(AI.getCallee()); if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember())) return false; auto *Method = CMI->getMember().getAbstractFunctionDecl(); if (!Method->isOverridden()) return true; ... return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 50

Slide 50 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { ... if (!Method->isOverridden()) return true; ClassHierarchyAnalysis::ClassList Subs; getAllSubclasses(CHA, CD, ClassType, AI.getModule(), Subs); auto *ImplMethod = CD->findImplementingMethod(Method); for (auto S : Subs) { auto *ImplFD = S->findImplementingMethod(Method); if (ImplFD != ImplMethod) return false; } return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 51

Slide 51 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { ... if (!Method->isOverridden()) return true; ClassHierarchyAnalysis::ClassList Subs; getAllSubclasses(CHA, CD, ClassType, AI.getModule(), Subs); auto *ImplMethod = CD->findImplementingMethod(Method); for (auto S : Subs) { auto *ImplFD = S->findImplementingMethod(Method); if (ImplFD != ImplMethod) return false; } return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 52

Slide 52 text

JT&⒎FDUJWFMZ'JOBM.FUIPE static bool isEffectivelyFinalMethod(FullApplySite AI, SILType ClassType, ClassDecl *CD, ClassHierarchyAnalysis *CHA) { ... if (!Method->isOverridden()) return true; ClassHierarchyAnalysis::ClassList Subs; getAllSubclasses(CHA, CD, ClassType, AI.getModule(), Subs); auto *ImplMethod = CD->findImplementingMethod(Method); for (auto S : Subs) { auto *ImplFD = S->findImplementingMethod(Method); if (ImplFD != ImplMethod) return false; } return true; } ϝιου͕z࣮࣭pOBMzͳύλʔϯ MJC4*-0QUJNJ[FS6UJMT%FWJSUVBMJ[FDQQ

Slide 53

Slide 53 text

0WFSSJEF͞ΕͭͭΠϯελϯε͕ ͦͷαϒΫϥεʹͳΓಘͳ͍৔߹ class Cat { func bark() {} } enum Tama {} enum Kuro {} class TamaCat: Cat { override func bark() {} } func callBark(cat: Cat) { cat.bark() }

Slide 54

Slide 54 text

class Cat { func bark() {} } enum Tama {} enum Kuro {} // CatͷαϒλΠϓͰ͸ͳ͍ class TamaCat: Cat { override func bark() {} } func callBark(cat: Cat) { cat.bark() } 0WFSSJEF͞ΕͭͭΠϯελϯε͕ ͦͷαϒΫϥεʹͳΓಘͳ͍৔߹

Slide 55

Slide 55 text

JT&⒎FDUJWFMZ'JOBM.FUIPE ϝιου͕z࣮࣭pOBMzͳύλʔϯ

Slide 56

Slide 56 text

ʮΘΜʯ໰୊

Slide 57

Slide 57 text

class Cat { func bark() -> String { return “ʹΌΜ" } } class Dog { func bark() -> String { return "ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) // ΘΜ ࠷దԽ͋Γͷ৔߹ Dog.barkϝιου͸non-final ΦʔόʔϥΠυ͞Ε͍ͯͳ͍ͷͰ”࣮࣭final” dog.bark()͕Static Dispatchʹ࠷దԽ͞ΕΔ

Slide 58

Slide 58 text

࠷దԽͳ͠ͷ৔߹ class Cat { func bark() -> String { return “ʹΌΜ" } } class Dog { func bark() -> String { return "ΘΜ" } } let cat = Cat() let dog = unsafeBitCast(cat, to: Dog.self) print(dog.bark()) // ʹΌΜ Whole Module࠷దԽ͕Φϑ Ϟδϡʔϧ಺ͰΦʔόʔϥΠυ͞ΕΔՄೳੑ͕͋Δ ΠϯελϯεͷϝλσʔλͷVTable͔Β Dynamic Dispatch͢Δ

Slide 59

Slide 59 text

%JTQBUDI 1FSGPSNBODF

Slide 60

Slide 60 text

LBUFJOPJHBLVLVO%JTQBUDI#FODINBSL

Slide 61

Slide 61 text

3VOUJNF1FSGPSNBODF /VNCFSPGEJTQBUDI $165JNF

Slide 62

Slide 62 text

·ͱΊ w %ZOBNJD%JTQBUDI͸΍͸Γ஗͍ w pOBM΍QSJWBUF͸ͪΌΜͱޮՌ͕͋Δ w ͕ɺίϯύΠϥ͕ݡ͍ͷͰେମ4UBUJD%JTQBUDIʹͳΔ w ίϯύΠϥΛಡΊ͹4XJGUͷڍಈ͕෼͔͓ͬͯ΋͠Ζ͍

Slide 63

Slide 63 text

w IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT4*-STU w IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT 0QUJNJ[BUJPO5JQTSTUSFEVDJOHEZOBNJDEJTQBUDI w !PNPDIJNFUBSV4XJGUͷδΣωϦοΫͳϓϩτίϧͷม਺͸ͳͥ࡞Εͳ͍ͷ͔ɺ ίϯύΠϧޙͷதؒݴޠΛݟͯߟ͑ͨ w IUUQTRJJUBDPNPNPDIJNFUBSVJUFNTCFFBBBFGB ࢀߟ