clangのARCは、コードをObjCからObjCに書き換えても機能しませんが、コード生成中に追加の保持/解放LLVMビットコードを発行します。つまり、LLVM IR /アセンブリレベルに移動せずに、コンパイラがどのようにそれを「修正」するかを知ることはできません。
あなたが言ったように、ARCがLLVMビットコードを発行する場合。コンパイルプロセスにかかる時間を短縮する目的で作成されていますか?(複雑でないObjCコード、ヘッダーファイルが少ない?)
コンパイラーがコードを通過する回数を減らすことができれば、常に優れています。
アセンブリレベルでコードを表示する例やユーティリティを教えてください。
アセンブリコードを取得するには、次のいずれかを実行できます。
コンパイラから直接アセンブリを生成します。コマンドラインで-S
、コンパイラを呼び出すときにフラグを追加します。結果は.S
、アセンブリコードを含むファイルです。Xcodeプロジェクトで、ソースコードファイルを開き、[製品](メニューバー)→ [出力の生成] → [アセンブリファイル]に移動します。
オブジェクトファイルを生成し、それを逆アセンブルします。組み込みコマンドotool -tvV <file>
は逆アセンブルを実行でき、otx(無料)やIDA(評価用に無料)などの高度なツールがあります。
ルート2の方がゴミの発生が少なく、逆アセンブルツールを構成してより有用な情報を生成できるためです。とにかく、どちらの方法でも、アセンブリコードを読み取れる必要があります。
このコードを例として取り上げます。
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
コンパイル後、次のアセンブリが作成されます(IDAを使用して分析)。
-[SomeAppDelegateアプリケーション:didFinishLaunchingWithOptions:]:
プッシュ{r4-r7、lr}
r7、sp、#0xCを追加
str.w r8、[sp、-#0x4]!
サブsp、sp、#0x18
movw r1、#(0x343c-0x2574); @selector(alloc)
mov r8、r0
movt.w r1、#0
mov r0、(0x3464-0x2576); _OBJC_CLASS _ $ _ UIWindow
r1、pcを追加
r0、pcを追加
ldr r1、[r1]
ldr r0、[r0]
blx _objc_msgSend
mov r1、(0x3440-0x258e); @selector(mainScreen)
mov r6、r0
movw r0、#(0x3468-0x2594); _OBJC_CLASS _ $ _ UIScreen
r1、pcを追加
movt.w r0、#0
r0、pcを追加
ldr r1、[r1]
ldr r0、[r0]
blx _objc_msgSend
mov r7、r7
blx _objc_retainAutoreleasedReturnValue
mov r5、r0
cbz r5、L25ba
movw r0、#(0x3444-0x25b2); @selector(bounds)
mov r1、r5
movt.w r0、#0
r0、pcを追加
ldr r2、[r0]
r0、sp、#0x8を追加します
blx _objc_msgSend_stret
b L25c4
L25ba:
r0、sp、#0x8を追加します
vmov.i32 q8、#0x80
vstmia r0、{d16-d17}
L25c4:
mov r1、(0x3448-0x25d2); @selector(initWithFrame :)
ldr r0、[sp、#0x10]
r1、pcを追加
ldr r2、[sp、#0x8]
ldr r3、[sp、#0xc]
ldr r4、[sp、#0x14]
stmea.w sp、{r0、r4}
mov r0、r6
ldr r1、[r1]
blx _objc_msgSend
mov r4、r0
mov r0、(0x344c-0x25F2); @selector(setWindow :)
mov r2、r4
r0、pcを追加
ldr r1、[r0]
mov r0、r8
blx _objc_msgSend
mov r0、r4
blx _objc_release
mov r0、r5
blx _objc_release
mov r0、(0x3450-0x2610); @selector(window)
r0、pcを追加
ldr r5、[r0]
mov r0、r8
mov r1、r5
blx _objc_msgSend
mov r7、r7
blx _objc_retainAutoreleasedReturnValue
mov r1、(0x3454-0x2630); @selector(whiteColor)
mov r6、r0
movw r0、#(0x346C-0x2636); _OBJC_CLASS _ $ _ UIColor
r1、pcを追加
movt.w r0、#0
r0、pcを追加
ldr r1、[r1]
ldr r0、[r0]
blx _objc_msgSend
mov r7、r7
blx _objc_retainAutoreleasedReturnValue
mov r4、r0
mov r0、(0x3458-0x2652); @selector(setBackgroundColor :)
mov r2、r4
r0、pcを追加
ldr r1、[r0]
mov r0、r6
blx _objc_msgSend
mov r0、r4
blx _objc_release
mov r0、r6
blx _objc_release
mov r0、r8
mov r1、r5
blx _objc_msgSend
mov r7、r7
blx _objc_retainAutoreleasedReturnValue
mov r4、r0
mov r0、(0x345C-0x2680); @selector(makeKeyAndVisible)
r0、pcを追加
ldr r1、[r0]
mov r0、r4
blx _objc_msgSend
mov r0、r4
blx _objc_release
movs r0、#1
sp、sp、#0x18を追加
ldr.w r8、[sp]、#4
pop {r4-r7、pc}
詳細に立ち入ることなく、多くの_objc_release
とが存在することがわかります_objc_retainAutoreleasedReturnValue
。これらは、コード生成中にARCが挿入するものです。手作業で逆コンパイルすると、次のようになります。
UIScreen* r5 = objc_retainAutoreleasedReturnValue([UIScreen mainScreen]);
CGRect sp8 = r5 != nil ? [r5 bounds] : CGRectZero;
UIWindow* r4 = [[UIWindow alloc] initWithFrame:sp8];
[self setWindow:r4];
objc_release(r4);
objc_release(r5);
UIWindow* r6a = objc_retainAutoreleasedReturnValue([self window])
UIColor* r4a = objc_retainAutoreleasedReturnValue([UIColor whiteColor])
[r6a setBackgroundColor:r4a];
objc_release(r4a);
objc_release(r6a);
UIWindow* r4b = objc_retainAutoreleasedReturnValue([self window])
[r4b makeKeyAndVisible];
objc_release(r4b);
return 1;
これは、 @croaldのリンクで説明されているものとまったく同じです。