Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Swiftとメソッドのアレコレ
@tarunon
1
自己紹介
@tarunon
イカガチ勢 2015-09-26現在
ランク50 ウデマエS55
守備範囲: Swift, Objective-
C, JavaScript, Java, etc…
2
Resume
3
復習Objective-C
Swiftは何故速い?
struct/enum
アクセス修飾子
Any vs Generics
Protocol Extension
optional func
Closure
復習Objective-C
復習Objective-C
Objective-Cは動的言語
objc_msgSend
ランタイムAPI
5
objc_msgSend
6
Class
IMP
void aFunction(id self, SEL _cmd) {
…
}
SEL
処理はCの関数と同等のIMPに存在
IMPへの参照とSelectorの組を持つ
objc_msgSend
7
objc_msgSend
Object
SEL
Arguments
objc_msgSendが

IMPを検索して実行する
高コスト!遅い!
objc_msgSend
8
「クリティカルな部分はCで書く」
「C++」
ランタイムAPI
9
クラスにメソッドを追加
クラスにプロパティを追加
Method Swizzling
クラスを追加
objc_msgSendの恩恵
10
クラスの継承
UIControl::addTarget:action:forControlEvents:
@optionalなメソッド(Protocol)
CoreData
モデルを定義するためにObjec...
Swiftは何故速い?
※LLVM中間コードが大量に出現します。ご注意下さい。
Swiftは何故速い?
12
@interface A : NSObject
@property (nonatomic) NSString *str;
@property (nonatomic) NSInteger integer;
@end
...
Swiftは何故速い?
13
clang -S -emit-llvm source.m
Swiftは何故速い?
14
@"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8
@"OBJC_IVAR_$_A._intege...
Swiftは何故速い?
15
@"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8
@"OBJC_IVAR_$_A._intege...
Swiftは何故速い?
16
%a = alloca %0*, align 8
%1 = load %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_"
%2 = load i8** @OBJC_...
Swiftは何故速い?
17
call void bitcast (i8* (i8*, i8*, ...)*
@objc_msgSend to void (i8*, i8*)*)(i8*
%8, i8* %7)
Swiftは何故速い?
18
class A {
var str: String?
var int: Int?
func function() {
}
}
Swiftは何故速い?
19
swiftc -emit-ir source.swift > source.ll
Swiftは何故速い?
20
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, ...
Swiftは何故速い?
21
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, ...
Swiftは何故速い?
22
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20U...
Swiftは何故速い?
23
store i8* %2, i8** getelementptr inbounds
(%VSs20UnsafeMutablePointer* @
%5 = call %swift.type* @_TMaC6sour...
Swiftは何故速い?
24
%11 = getelementptr inbounds void
(%C6source1A*)** %10, i64 9
Swiftは何故速い?
25
class A: NSObject {
var str: String?
var int: Int?
func function() {
}
}
Swiftは何故速い?
26
@8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00"
@_METACLASS_DATA__TtC6source1A = private co...
Swiftは何故速い?
27
@8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00"
@_METACLASS_DATA__TtC6source1A = private co...
Swiftは何故速い?
28
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20U...
Swiftは何故速い?
29
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20U...
Swiftは何故速い?
classメソッドの呼び出しが
objc_msgSendからvtableに変更されパ
フォーマンスが向上した
NSObjectを継承すると、objc_msgSend
が使用できる状態になるが、vtableも存
在し、vt...
Swiftは何故速い?
vtableを利用しているため、ランタ
イムAPIを使ったテクニックの幾つか
が使えなくなっていることに注意
Method SwizzlingはSwift製の

クラスには無効
31
struct/enum
struct/enum
33
struct A {
var str: String?
var int: Int?
func function() {
}
}
34
swiftc -emit-ir source.swift > source.ll
struct/enum
struct/enum
35
@_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external...
struct/enum
36
@_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external...
struct/enum
37
define hidden void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41)) #0 ...
struct/enum
38
%.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0
%31 = bitcast %Sq* %.str to { i64, i64, i64 }*...
struct/enum
39
%.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0
%31 = bitcast %Sq* %.str to { i64, i64, i64 }*...
struct/enum
40
struct/enumのメソッドはただの関数への
エイリアス
selfを利用する際にコピーが発生しない
vtableよりも高パフォーマンス
struct/enumは値型であるため、事ある毎
にコピーのコストが発生する
アクセス修飾子の話
アクセス修飾子
Swiftのアクセス修飾子は3種類
public
internal
private
classにはfinal修飾子もある
classメソッドの実行方法が変化
42
アクセス修飾子
Swiftのアクセス修飾子は3種類
public…フレームワーク外から参照可
internal…同一フレームワーク内から参照可
private…同一ファイル内から参照可
クラスにはfinal修飾子もある
43
アクセス修飾子
44
class A: NSObject {
var str: String?
var int: Int?
private func function() {
print(self)
}
}
アクセス修飾子
45
@_Tv6source1aCS_1A = global %C6source1A* null, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5I...
アクセス修飾子
46
@"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section
"__TEXT,__objc_methname,cstrin...
アクセス修飾子
47
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20Unsaf...
アクセス修飾子
48
class B: A {
override private func function() {
}
}
アクセス修飾子
49
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20Unsaf...
アクセス修飾子
private修飾子
終端のメソッドは直接呼び出し
オーバーライドされたものはvtable
selectorは存在しない (objc_msgSendできない)
final修飾子
直接呼び出し
selectorは存在しない (obj...
アクセス修飾子
privateやfinalのついたメソッドを
addTarget:action:に渡すと死ぬ
隠蔽したい場合は?
モジュール切ってinternalに

 しましょう
51
Any vs Generics
Any
Swiftで定義された「なんでも代入可
能な型」
typealias protocol<>
Objective-Cのid型はAnyObjectに
相当
53
Any
Optionalの値を格納することも可能だが…
Any?型の値をAny型に格納することも可
能。
ネストしたOptionalを取り出すのは面倒。
予めAny?で宣言するが吉。
54
Any
例えばString?型の値をAny型に格納した場合、
a as? Optional<Any>では取り出せない。

a as? Optional<String>で取り出す必要があ
る。
Any型の引数には、渡した変数が型ごと含ま
れている...
Any
56
define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias
nocapture dereferenceable(32)) #0 {
entry:
%1 =...
Any
57
define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias
nocapture dereferenceable(32)) #0 {
entry:
%1 =...
Generics
Generics引数は、型引数と曖昧な型
に分割されて渡される。
Genericsの制約が増えれば、型引数
も増える。
58
Generics
59
define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque*
noalias nocapture, %swift.type* %A, i8** ...
Generics
60
define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque*
noalias nocapture, %swift.type* %A, i8** ...
Any vs Generics
特殊な要求が無いのであれば、
Genericsを使うべき
とりあえずAnyやAnyObjectの引数
はGenericsにしてみよう
61
Protocol Extension
Protocol Extension
63
protocol P {
}
extension P {
func function() {
}
}
class A: NSObject, P {
var str: String?
var int: ...
Protocol Extension
64
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgv...
Protocol Extension
65
call void
@_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.t
ype* %6, i8** getelementptr inbo...
が
型がProtocolだった場合、
Protocol Extension
67
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgv...
Protocol Extension
68
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgv...
optional func
optional func
70
@objc protocol Delegate: NSObjectProtocol {
optional func function()
}
71
swiftc -emit-ir source.swift > source.ll
struct/enum
optional func
できませんでした。。。
コンパイラが賢い?
同一ファイル内はチェックしてい
るっぽい
72
Closure
Closure
Swiftではメソッドへの参照を
Closureとして利用することが可能
(2.0 )
74
Closure
75
class A: NSObject {
var str: String?
var int: Int?
private func function() {
print(self)
}
}
var a = A()
var m ...
Closure
76
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20Unsaf...
Closure
77
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20Unsaf...
Swiftのこれから
Swiftのこれから
Objective-Cランタイムから切り離
される可能性
objc_msgSendを使わなくても、代
替可能な環境が出来つつある
79
Swiftのこれから
addTarget:action:
クロージャで代替が十分可能
メソッドをクロージャとして渡せるよ
うになった(実際はラップされている)
ReferenceCountingの問題
80
Swiftのこれから
optional func
Protocol Extensionにデフォルト
実装を書くことで代替可能に見え
るが…
ちょっと挙動がバグっぽい
81
Swiftのこれから
optional func
Protocol Extensionにデフォルト
実装を書くことで代替可能に見え
るが…
82
まとめ
Swift実際速い
struct/enumはメソッドが直接実行なの
で超速い
private, final付けると直接実行になるの
で超速い
Objective-Cランタイムに依存しない方向へ
83
Upcoming SlideShare
Loading in …5
×

Swiftとメソッドのアレコレ

2015-09-27 Hacker Tackleにて

  • Login to see the comments

Swiftとメソッドのアレコレ

  1. 1. Swiftとメソッドのアレコレ @tarunon 1
  2. 2. 自己紹介 @tarunon イカガチ勢 2015-09-26現在 ランク50 ウデマエS55 守備範囲: Swift, Objective- C, JavaScript, Java, etc… 2
  3. 3. Resume 3 復習Objective-C Swiftは何故速い? struct/enum アクセス修飾子 Any vs Generics Protocol Extension optional func Closure
  4. 4. 復習Objective-C
  5. 5. 復習Objective-C Objective-Cは動的言語 objc_msgSend ランタイムAPI 5
  6. 6. objc_msgSend 6 Class IMP void aFunction(id self, SEL _cmd) { … } SEL 処理はCの関数と同等のIMPに存在 IMPへの参照とSelectorの組を持つ
  7. 7. objc_msgSend 7 objc_msgSend Object SEL Arguments objc_msgSendが
 IMPを検索して実行する 高コスト!遅い!
  8. 8. objc_msgSend 8 「クリティカルな部分はCで書く」 「C++」
  9. 9. ランタイムAPI 9 クラスにメソッドを追加 クラスにプロパティを追加 Method Swizzling クラスを追加
  10. 10. objc_msgSendの恩恵 10 クラスの継承 UIControl::addTarget:action:forControlEvents: @optionalなメソッド(Protocol) CoreData モデルを定義するためにObjective-Cランタイ ムを駆使
  11. 11. Swiftは何故速い? ※LLVM中間コードが大量に出現します。ご注意下さい。
  12. 12. Swiftは何故速い? 12 @interface A : NSObject @property (nonatomic) NSString *str; @property (nonatomic) NSInteger integer; @end @implementation A - (void)function { } @end
  13. 13. Swiftは何故速い? 13 clang -S -emit-llvm source.m
  14. 14. Swiftは何故速い? 14 @"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8 @"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8 @_objc_empty_cache = external global %struct._objc_cache @"OBJC_METACLASS_$_NSObject" = external global %struct._class_t @OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1 @"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 @"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_CLASS_$_NSObject" = external global %struct._class_t @OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast (%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)* @"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8 @OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8* getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t { i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 @OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1 @"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]* @OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]* @OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8 @"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2 x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8 @"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
  15. 15. Swiftは何故速い? 15 @"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8 @"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8 @_objc_empty_cache = external global %struct._objc_cache @"OBJC_METACLASS_$_NSObject" = external global %struct._class_t @OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1 @"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 @"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_CLASS_$_NSObject" = external global %struct._class_t @OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast (%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)* @"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8 @OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8* getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t { i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 @OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1 @"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]* @OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]* @OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8 @"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2 x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8 @"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8 Selectorの宣言
  16. 16. Swiftは何故速い? 16 %a = alloca %0*, align 8 %1 = load %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" %2 = load i8** @OBJC_SELECTOR_REFERENCES_, !invariant.load !6 %3 = bitcast %struct._class_t* %1 to i8* %4 = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %3, i8* %2) %5 = bitcast i8* %4 to %0* store %0* %5, %0** %a, align 8 %6 = load %0** %a, align 8 %7 = load i8** @OBJC_SELECTOR_REFERENCES_17, !invariant.load !6 %8 = bitcast %0* %6 to i8* call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* %8, i8* %7) ret i32 0
  17. 17. Swiftは何故速い? 17 call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* %8, i8* %7)
  18. 18. Swiftは何故速い? 18 class A { var str: String? var int: Int? func function() { } }
  19. 19. Swiftは何故速い? 19 swiftc -emit-ir source.swift > source.ll
  20. 20. Swiftは何故速い? 20 @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint (%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }
  21. 21. Swiftは何故速い? 21 @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint (%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 } vtable
  22. 22. Swiftは何故速い? 22 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = bitcast %C6source1A* %7 to %swift.refcounted* call void @swift_retain_noresult(%swift.refcounted* %8) #3 %9 = bitcast %C6source1A* %7 to %swift.type** %.metadata = load %swift.type** %9, align 8 %10 = bitcast %swift.type* %.metadata to void (%C6source1A*)** %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9 %.metadata1 = load void (%C6source1A*)** %11, align 8, !invariant.load !29 %12 = bitcast void (%C6source1A*)* %.metadata1 to i8* %13 = bitcast i8* %12 to void (%C6source1A*)* call void %13(%C6source1A* %7) call void bitcast (void (%swift.refcounted*)* @swift_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0
  23. 23. Swiftは何故速い? 23 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @ %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = bitcast %C6source1A* %7 to %swift.refcounted* call void @swift_retain_noresult(%swift.refcounted* %8) #3 %9 = bitcast %C6source1A* %7 to %swift.type** %.metadata = load %swift.type** %9, align 8 %10 = bitcast %swift.type* %.metadata to void (%C6source1A*)** %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9 %.metadata1 = load void (%C6source1A*)** %11, align 8, %12 = bitcast void (%C6source1A*)* %.metadata1 to i8* %13 = bitcast i8* %12 to void (%C6source1A*)* call void %13(%C6source1A* %7)
  24. 24. Swiftは何故速い? 24 %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9
  25. 25. Swiftは何故速い? 25 class A: NSObject { var str: String? var int: Int? func function() { } }
  26. 26. Swiftは何故速い? 26 @8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @9 = private unnamed_addr constant [11 x i8] c"C6source1A00" @10 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip"
  27. 27. Swiftは何故速い? 27 @8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @9 = private unnamed_addr constant [11 x i8] c"C6source1A00" @10 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip" Selectorの宣言 vtable
  28. 28. Swiftは何故速い? 28 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0
  29. 29. Swiftは何故速い? 29 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0 objc_msgSendではない
  30. 30. Swiftは何故速い? classメソッドの呼び出しが objc_msgSendからvtableに変更されパ フォーマンスが向上した NSObjectを継承すると、objc_msgSend が使用できる状態になるが、vtableも存 在し、vtableが優先的に使用される 30
  31. 31. Swiftは何故速い? vtableを利用しているため、ランタ イムAPIを使ったテクニックの幾つか が使えなくなっていることに注意 Method SwizzlingはSwift製の
 クラスには無効 31
  32. 32. struct/enum
  33. 33. struct/enum 33 struct A { var str: String? var int: Int? func function() { } }
  34. 34. 34 swiftc -emit-ir source.swift > source.ll struct/enum
  35. 35. struct/enum 35 @_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64, %swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)] @0 = private unnamed_addr constant [11 x i8] c"V6source1A00" @1 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*, i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 }
  36. 36. struct/enum 36 @_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64, %swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)] @0 = private unnamed_addr constant [11 x i8] c"V6source1A00" @1 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*, i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 } functionの記述が存在しない
  37. 37. struct/enum 37 define hidden void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41)) #0 { entry: %.str = getelementptr inbounds %V6source1A* %0, i32 0, i32 0 %1 = bitcast %Sq* %.str to { i64, i64, i64 }* %2 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 0 %3 = load i64* %2, align 8 %4 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 1 %5 = load i64* %4, align 8 %6 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 2 %7 = load i64* %6, align 8 %8 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %9 = bitcast [1 x i8]* %8 to i1* %10 = load i1* %9, align 8 %.int = getelementptr inbounds %V6source1A* %0, i32 0, i32 2 %11 = bitcast %Sq.17* %.int to i64* %12 = load i64* %11, align 8 %13 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %14 = bitcast [1 x i8]* %13 to i1* %15 = load i1* %14, align 8 ret void }
  38. 38. struct/enum 38 %.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0 %31 = bitcast %Sq* %.str to { i64, i64, i64 }* %32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0 store i64 %21, i64* %32, align 8 %33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1 store i64 %22, i64* %33, align 8 %34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2 store i64 %23, i64* %34, align 8 %35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %36 = bitcast [1 x i8]* %35 to i1* store i1 %24, i1* %36, align 8 %.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2 %37 = bitcast %Sq.17* %.int to i64* store i64 %25, i64* %37, align 8 %38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %39 = bitcast [1 x i8]* %38 to i1* store i1 %26, i1* %39, align 8 call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2) br i1 %24, label %43, label %40
  39. 39. struct/enum 39 %.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0 %31 = bitcast %Sq* %.str to { i64, i64, i64 }* %32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0 store i64 %21, i64* %32, align 8 %33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1 store i64 %22, i64* %33, align 8 %34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2 store i64 %23, i64* %34, align 8 %35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %36 = bitcast [1 x i8]* %35 to i1* store i1 %24, i1* %36, align 8 %.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2 %37 = bitcast %Sq.17* %.int to i64* store i64 %25, i64* %37, align 8 %38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %39 = bitcast [1 x i8]* %38 to i1* store i1 %26, i1* %39, align 8 call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2) br i1 %24, label %43, label %40 関数を直接実行している
  40. 40. struct/enum 40 struct/enumのメソッドはただの関数への エイリアス selfを利用する際にコピーが発生しない vtableよりも高パフォーマンス struct/enumは値型であるため、事ある毎 にコピーのコストが発生する
  41. 41. アクセス修飾子の話
  42. 42. アクセス修飾子 Swiftのアクセス修飾子は3種類 public internal private classにはfinal修飾子もある classメソッドの実行方法が変化 42
  43. 43. アクセス修飾子 Swiftのアクセス修飾子は3種類 public…フレームワーク外から参照可 internal…同一フレームワーク内から参照可 private…同一ファイル内から参照可 クラスにはfinal修飾子もある 43
  44. 44. アクセス修飾子 44 class A: NSObject { var str: String? var int: Int? private func function() { print(self) } }
  45. 45. アクセス修飾子 45 @_Tv6source1aCS_1A = global %C6source1A* null, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_swiftEmptyArrayStorage = external global %VSC23_SwiftEmptyArrayStorage, align 8 @_TWvdvC6source1A3strGSqSS_ = global i64 16, align 8 @"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(dealloc)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8 @"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]* @"01L_selector_data(allocWithZone:)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWVBO = external global i8* @"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) } @"OBJC_CLASS_$_NSObject" = external global %objc_class @_objc_empty_cache = external global %swift.opaque @_objc_empty_vtable = external global %swift.opaque @0 = private unnamed_addr constant [4 x i8] c"str00" @1 = private unnamed_addr constant [1 x i8] zeroinitializer @2 = private unnamed_addr constant [22 x i8] c"T@22NSString22,N,C,Vstr00" @"01L_selector_data(str)" = internal constant [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @3 = private unnamed_addr constant [8 x i8] c"@16@0:800" @"01L_selector_data(setStr:)" = internal constant [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @4 = private unnamed_addr constant [11 x i8] c"v24@0:8@1600" @5 = private unnamed_addr constant [4 x i8] c"int00" @"01L_selector_data(.cxx_destruct)" = internal constant [14 x i8] c".cxx_destruct00", section "__TEXT,__objc_methname,cstring_literals", align 1 @6 = private unnamed_addr constant [3 x i8] c"@?00" @"OBJC_METACLASS_$_NSObject" = external global %objc_class @7 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [4 x { i8*, i8*, i8* }] } { i32 24, i32 4, [4 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), { i32, i32, [4 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @8 = private unnamed_addr constant [11 x i8] c"C6source1A00" @9 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @8, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @9, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_ = hidden constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip" functionのSelectorが存在しない
  46. 46. アクセス修飾子 46 @"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(dealloc)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8 @"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]* @"01L_selector_data(allocWithZone:)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWVBO = external global i8* @"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_ $_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) } @"OBJC_CLASS_$_NSObject" = external global %objc_class
  47. 47. アクセス修飾子 47 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 call void @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*) (%C6source1A* %7) #4 ret i32 0 関数を直接実行している
  48. 48. アクセス修飾子 48 class B: A { override private func function() { } }
  49. 49. アクセス修飾子 49 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 %19 = call %swift.type* @_TMaC6source1B() #2 %20 = call %C6source1B* @_TFC6source1BCfMS0_FT_S0_(%swift.type* %19) store %C6source1B* %20, %C6source1B** @_Tv6source1bCS_1B, align 8 %21 = load %C6source1B** @_Tv6source1bCS_1B, align 8 %22 = call %C6source1B* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1B* (%C6source1B*)*)(%C6source1B* %21) #3 call void @_TFC6source1BP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1B* %21) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1B*)*)(%C6source1B* %21) #3 ret i32 0 直接実行 vtable
  50. 50. アクセス修飾子 private修飾子 終端のメソッドは直接呼び出し オーバーライドされたものはvtable selectorは存在しない (objc_msgSendできない) final修飾子 直接呼び出し selectorは存在しない (objc_msgSendできない) 50 selectorは存在します
  51. 51. アクセス修飾子 privateやfinalのついたメソッドを addTarget:action:に渡すと死ぬ 隠蔽したい場合は? モジュール切ってinternalに
  しましょう 51
  52. 52. Any vs Generics
  53. 53. Any Swiftで定義された「なんでも代入可 能な型」 typealias protocol<> Objective-Cのid型はAnyObjectに 相当 53
  54. 54. Any Optionalの値を格納することも可能だが… Any?型の値をAny型に格納することも可 能。 ネストしたOptionalを取り出すのは面倒。 予めAny?で宣言するが吉。 54
  55. 55. Any 例えばString?型の値をAny型に格納した場合、 a as? Optional<Any>では取り出せない。
 a as? Optional<String>で取り出す必要があ る。 Any型の引数には、渡した変数が型ごと含ま れているため。暗黙のキャストは走っていな い。 55
  56. 56. Any 56 define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias nocapture dereferenceable(32)) #0 { entry: %1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1 %.metadata = load %swift.type** %1, align 8 %2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0 %3 = bitcast %swift.type* %.metadata to i8*** %4 = getelementptr inbounds i8*** %3, i64 -1 %.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load ! 29, !dereferenceable !30 %5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29 %destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)* call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1 ret void }
  57. 57. Any 57 define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias nocapture dereferenceable(32)) #0 { entry: %1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1 %.metadata = load %swift.type** %1, align 8 %2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0 %3 = bitcast %swift.type* %.metadata to i8*** %4 = getelementptr inbounds i8*** %3, i64 -1 %.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load ! 29, !dereferenceable !30 %5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29 %destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)* call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1 ret void } Any型
  58. 58. Generics Generics引数は、型引数と曖昧な型 に分割されて渡される。 Genericsの制約が増えれば、型引数 も増える。 58
  59. 59. Generics 59 define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.P) #0 { entry: %A1 = alloca %swift.type*, align 8 store %swift.type* %A, %swift.type** %A1, align 8 %1 = bitcast %swift.type* %A to i8*** %2 = getelementptr inbounds i8*** %1, i64 -1 %A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, ! dereferenceable !30 %3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4 %4 = load i8** %3, align 8, !invariant.load !29 %destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* %0, %swift.type* %A) #1 ret void }
  60. 60. Generics 60 define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.P) #0 { entry: %A1 = alloca %swift.type*, align 8 store %swift.type* %A, %swift.type** %A1, align 8 %1 = bitcast %swift.type* %A to i8*** %2 = getelementptr inbounds i8*** %1, i64 -1 %A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, ! dereferenceable !30 %3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4 %4 = load i8** %3, align 8, !invariant.load !29 %destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* %0, %swift.type* %A) #1 ret void } 型引数 
  61. 61. Any vs Generics 特殊な要求が無いのであれば、 Genericsを使うべき とりあえずAnyやAnyObjectの引数 はGenericsにしてみよう 61
  62. 62. Protocol Extension
  63. 63. Protocol Extension 63 protocol P { } extension P { func function() { } } class A: NSObject, P { var str: String? var int: Int? }
  64. 64. Protocol Extension 64 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %9 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %8) #3 store %C6source1A* %8, %C6source1A** %2, align 8 %10 = bitcast %C6source1A** %2 to %swift.opaque* call void @_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.type* %6, i8** getelementptr inbounds ([0 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), %swift.opaque* noalias nocapture %10) %11 = load %C6source1A** %2, align 8 call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %11) #3 ret i32 0
  65. 65. Protocol Extension 65 call void @_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.t ype* %6, i8** getelementptr inbounds ([0 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), %swift.opaque* noalias nocapture %10)
  66. 66. が 型がProtocolだった場合、
  67. 67. Protocol Extension 67 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8 %_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 %8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8 %9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 store i8** %9, i8*** %10, align 8 %11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8*** %13 = getelementptr inbounds i8*** %12, i64 -1 %_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30 %14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1 %15 = load i8** %14, align 8, !invariant.load !29 %initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* %16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3 %17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 %.metadata = load %swift.type** %17, align 8 %18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %19 = bitcast %swift.type* %.metadata to i8*** %20 = getelementptr inbounds i8*** %19, i64 -1 %.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30 %21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2 %22 = load i8** %21, align 8, !invariant.load !29 %projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)* %23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3 %24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 %witness-table = load i8*** %24, align 8 store %swift.type* %.metadata, %swift.type** %.metadata1, align 8 %25 = load i8** %witness-table, align 8, !invariant.load !29 %26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)* call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata)
  68. 68. Protocol Extension 68 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8 %_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 %8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8 %9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 store i8** %9, i8*** %10, align 8 %11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8*** %13 = getelementptr inbounds i8*** %12, i64 -1 %_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30 %14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1 %15 = load i8** %14, align 8, !invariant.load !29 %initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* %16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3 %17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 %.metadata = load %swift.type** %17, align 8 %18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %19 = bitcast %swift.type* %.metadata to i8*** %20 = getelementptr inbounds i8*** %19, i64 -1 %.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30 %21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2 %22 = load i8** %21, align 8, !invariant.load !29 %projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)* %23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3 %24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 %witness-table = load i8*** %24, align 8 store %swift.type* %.metadata, %swift.type** %.metadata1, align 8 %25 = load i8** %witness-table, align 8, !invariant.load !29 %26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)* call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata) witness-tableを利用
  69. 69. optional func
  70. 70. optional func 70 @objc protocol Delegate: NSObjectProtocol { optional func function() }
  71. 71. 71 swiftc -emit-ir source.swift > source.ll struct/enum
  72. 72. optional func できませんでした。。。 コンパイラが賢い? 同一ファイル内はチェックしてい るっぽい 72
  73. 73. Closure
  74. 74. Closure Swiftではメソッドへの参照を Closureとして利用することが可能 (2.0 ) 74
  75. 75. Closure 75 class A: NSObject { var str: String? var int: Int? private func function() { print(self) } } var a = A() var m = a.function
  76. 76. Closure 76 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 %9 = call { i8*, %swift.refcounted* } @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7) %10 = extractvalue { i8*, %swift.refcounted* } %9, 0 %11 = extractvalue { i8*, %swift.refcounted* } %9, 1 store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 %12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 %13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 call void @swift_retain_noresult(%swift.refcounted* %13) #4 %14 = bitcast i8* %12 to void (%swift.refcounted*)* call void %14(%swift.refcounted* %13) ret i32 0
  77. 77. Closure 77 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 %9 = call { i8*, %swift.refcounted* } @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7) %10 = extractvalue { i8*, %swift.refcounted* } %9, 0 %11 = extractvalue { i8*, %swift.refcounted* } %9, 1 store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 %12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 %13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 call void @swift_retain_noresult(%swift.refcounted* %13) #4 %14 = bitcast i8* %12 to void (%swift.refcounted*)* call void %14(%swift.refcounted* %13) ret i32 0 Closureを生成してラッピング
  78. 78. Swiftのこれから
  79. 79. Swiftのこれから Objective-Cランタイムから切り離 される可能性 objc_msgSendを使わなくても、代 替可能な環境が出来つつある 79
  80. 80. Swiftのこれから addTarget:action: クロージャで代替が十分可能 メソッドをクロージャとして渡せるよ うになった(実際はラップされている) ReferenceCountingの問題 80
  81. 81. Swiftのこれから optional func Protocol Extensionにデフォルト 実装を書くことで代替可能に見え るが… ちょっと挙動がバグっぽい 81
  82. 82. Swiftのこれから optional func Protocol Extensionにデフォルト 実装を書くことで代替可能に見え るが… 82
  83. 83. まとめ Swift実際速い struct/enumはメソッドが直接実行なの で超速い private, final付けると直接実行になるの で超速い Objective-Cランタイムに依存しない方向へ 83

×