Czy można zobaczyć kod wygenerowany przez ARC w czasie kompilacji?
Przeczytałem Transitioning to Arc Release Notes w sekcji "Summary". Powiedzieli:
ARC działa poprzez dodawanie kodu w czasie kompilacji, aby zapewnić, że obiekty działają tak długo, jak to konieczne, ale już nie. Koncepcyjnie wynika to z tego samego konwencje zarządzania pamięcią jako ręczne zliczanie referencji (opisane w Advanced Memory Management Programming Guide) poprzez dodanie odpowiednie zarządzanie pamięcią wymaga od ciebie.
Aby kompilator Wygeneruj poprawny kod
Ciekawe jaki wynik ten ARC poprawił nasz kod.
Moje pytanie: Czy możemy zobaczyć zmianę? (w terminach alloc , retain , assign lub release .Nie poziom montażu !)
Powód: ponieważ myślę, że dobrze jest zobaczyć kod najlepszej praktyki w rozwoju starej tradycji bez trybu ARC.
3 answers
ARC w clang nie działa przepisując kod z ObjC do ObjC, ale emitując dodatkowy bitcode zachowaj / zwolnij LLVM podczas code-gen. oznacza to, że nie jest możliwe, aby wiedzieć, jak kompilator "naprawić" go bez przechodzenia do poziomu LLVM IR/assembly.
Jeśli ARC emituje BITCODE LLVM, jak powiedziałeś. Czy jest to zrobione w celu, który zużywa mniej czasu w procesie kompilacji? (mniej skomplikowany kod obiektu, mniej pliku nagłówkowego?)
Jest zawsze lepiej, jeśli kompilator może zmniejszyć liczba przejść przez kod.
Możesz mi pokazać jakiś przykład lub narzędzie, które pokazuje kod na poziomie złożenia?
Aby uzyskać kod assembly, możesz albo
Generuje assembly bezpośrednio z kompilatora. W wierszu poleceń Dodaj znacznik
-S
podczas wywoływania kompilatora. Rezultatem jest plik.S
zawierający kod złożenia. W projekcie Xcode otwórz plik kodu źródłowego, a następnie przejdź do Product (na pasku menu) → Wygeneruj Wyjście → Plik Assembly .Wygenerować plik obiektowy, a następnie go zdemontować. Wbudowane polecenie {[5] } może wykonywać demontaż, a istnieją zaawansowane narzędzia, takie jak otx (bezpłatne) lub IDA (bezpłatne do oceny).
Wolę route 2, ponieważ generuje mniej śmieci, a narzędzie do demontażu można skonfigurować tak, aby wytwarzało więcej użytecznych informacji. W każdym razie, przy obu metodach musisz być w stanie odczytać montaż kod.
Weź ten kod jako przykład:
- (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;
}
Po skompilowaniu zostanie wytworzony następujący zestaw (analizowany przy użyciu IDA):
-[SomeAppDelegate application:didFinishLaunchingWithOptions:]: push {r4-r7,lr} add r7, sp, #0xC str.w r8, [sp,-#0x4]! sub sp, sp, #0x18 movw r1, #(0x343c - 0x2574) ; @selector(alloc) mov r8, r0 movt.w r1, #0 mov r0, (0x3464 - 0x2576) ; _OBJC_CLASS_$_UIWindow add r1, pc add 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 add r1, pc movt.w r0, #0 add 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 add r0, pc ldr r2, [r0] add r0, sp, #0x8 blx _objc_msgSend_stret b L25c4 L25ba: add r0, sp, #0x8 vmov.i32 q8, #0x80 vstmia r0, {d16-d17} L25c4: mov r1, (0x3448 - 0x25d2) ; @selector(initWithFrame:) ldr r0, [sp,#0x10] add 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 add 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) add 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 add r1, pc movt.w r0, #0 add 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 add 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) add r0, pc ldr r1, [r0] mov r0, r4 blx _objc_msgSend mov r0, r4 blx _objc_release movs r0, #1 add sp, sp, #0x18 ldr.w r8, [sp], #4 pop {r4-r7,pc}
Bez wchodzenia w szczegóły, widać, że jest ich wiele _objc_release
i _objc_retainAutoreleasedReturnValue
. oto co Arc wstawia podczas kodu-gen. Dekompilując go ręcznie, otrzymamy:
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;
Który jest dokładnie taki sam jak to, co opisuje link @c roald.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:00:29
Mike Ash ma bardzo pouczającą dyskusję na temat implementacji ARC tutaj: http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html
Omawia to na poziomie wstawiania wywołań funkcji C (objc_retain (), objc_release (), objc_retainAutoreleaseReturnValue () i kilku innych, jeśli byłoby to dla ciebie pomocne. Napisany w ten sposób kompilator może używać optymalizacji wywołania ogonowego w celu wyeliminowania niepotrzebnych kroków.
Krótka odpowiedź, w związku z tym ARC nie używa tych samych metod [zachowaj]/[wydaj], których używalibyśmy w starszych wersjach Objecive C, więc zobaczenie wstępnie przetworzonego kodu Arc niekoniecznie instruowałoby Cię, jak to zrobić samemu.
ARC nie jest niczym niezwykłym w implementacji jako etap wstępnego przetwarzania w kompilatorze -- wierzę, że wiele funkcji Objective C jest zaimplementowanych w ten sposób.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-12 14:14:43
Nie Nie można wchodzić w takie szczegóły bez wchodzenia w szczegóły poziomu montażu LLVM.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-12 16:53:57