Slide 1

Slide 1 text

Objec&ve(C*Ini&alisa&on before&your&app&had&its&morning&cup&of&coffee.

Slide 2

Slide 2 text

Intro objc4!library!is!open!sourced: h2p:/ /opensource.apple.com/source/objc4/objc48646/

Slide 3

Slide 3 text

Objec&ve(C • 1970&'&Alan&Kay&and&others&developed&Smalltalk. • 1980&'&Cox&and&Love&developed&set&of&C&preprocessing¯os&to& support&Smalltalk&OOP&features. • 1988&'&NeXT&licensed&ObjecKve'C,&added&support&to&GCC. • 1996&'&Apple&(NeXT)&built&Mac&OS&using&ObjecKve'C. • 2007&'&ObjecKve'C&2.0:&non'fragile&classes&(release&2007). • 2014&'&SwiV:&ObjecKve'C&without&C.

Slide 4

Slide 4 text

Ini$alisa$on • Dynamic)messaging,)associated)objects,)swizzling,)class)posing) and)more)8)this)is)where)it)all)begins. • _objc_init • Called)by)/usr/lib/libSystem. • Encapsulates)all)ini>aliza>on)steps.

Slide 5

Slide 5 text

Environment environ_init • Reads'environment'variables,'prints'help. • Your'chance'to'specify'OBJC_HELP'and'other'flags.

Slide 6

Slide 6 text

Locks lock_init • Sets&up&locks&requires&for&thread4safe&run6me&modifica6ons&of: • Registered&selectors. • Classes,&methods,&protocols,&caches&etc. • Temporary&list&of&classes&and&protocols&to&call&+load&on.

Slide 7

Slide 7 text

Excep&ons exception_init • Fairly(straigh-orward(excep5on(setup(with( std::set_terminate. • _objc_default_uncaught_exception_handler(expected( to(be(overridden(by(Founda5on.

Slide 8

Slide 8 text

dyld!handlers • unmap_image • Registering*first*to*be*prepared*if*someone*unloads*image* during*the*+load. • Finds*appropriate*headers*to*unload*&*removes*classes*from* loadable_classes*list. • Frees*classes*&*their*isa.

Slide 9

Slide 9 text

dyld!handlers • map_images"&"load_images • Process"the"given"images"which"are"being"mapped"in"by"dyld. • All"class"registra:on"and"fixups"are"performed,"and"+load" methods"are"called. • List"of"headers"is"in"boAomBup"order.

Slide 10

Slide 10 text

Thank&you.

Slide 11

Slide 11 text

One$more$thing.

Slide 12

Slide 12 text

[obj message];

Slide 13

Slide 13 text

objc_msgSend(obj, @selector(message));

Slide 14

Slide 14 text

objc_msgSend Any$message$passing$can$be$rewri0en$using$objc_msgSend // safe release while ([obj retainCount] > 0) { [obj release]; }

Slide 15

Slide 15 text

objc_msgSend Any$message$passing$can$be$rewri0en$using$objc_msgSend // fast safe release while (objc_msgSend(obj, @selector(retainCount)) > 0) { (objc_msgSend(obj, @selector(release)); }

Slide 16

Slide 16 text

So#you#want#to#call#objc_msgSend#directly // fast safe release typedef NSUInteger (*retain_count_t)(id, SEL); typedef NSUInteger (*release_t)(id, SEL); while (((retain_count_t)objc_msgSend)(obj, sel_getUid("retainCount")) > 0) { ((release_t)objc_msgSend)(obj, sel_getUid("release")); }

Slide 17

Slide 17 text

The$Objec)ve+C$language$defers$as$many$decisions$as$it$can$from$ compile$)me$and$link$)me$to$run)me !!"Objec(ve!C"Run(me"Reference.

Slide 18

Slide 18 text

objc_msgSend • Group'of'methods. • Declared'in'message.h. • Implemented'in'objc-msg-x86_64.s.'Wait,'what? • arm,'arm64 • i386,'simulator-i386 • x86_64,'simulator-x86_64 • win32

Slide 19

Slide 19 text

objc_msgSend ENTRY objc_msgSend MESSENGER_START cbz r0, LNilReceiver_f ldr r9, [r0] // r9 = self->isa CacheLookup NORMAL // calls IMP or LCacheMiss LCacheMiss: MESSENGER_END_SLOW ldr r9, [r0, #ISA] // class = receiver->isa b __objc_msgSend_uncached LNilReceiver: mov r1, #0 MESSENGER_END_NIL bx lr LMsgSendExit: END_ENTRY objc_msgSend

Slide 20

Slide 20 text

objc_msgSend • Tail&op)mised • Dropped&support&for&vtable • ????

Slide 21

Slide 21 text

objc_msgSend:"fast"path. • Check'for'ignored'selectors'(GC)'and'short6circuit. • Check'for'nil'target'&'tagged'pointer. • Jump'to'nil'receiver'handler'or'cleanup'and'return. • Return'nil'(or'primi?ve'equivalent). • Search'the'class’s'method'cache'for'the'method'IMP.

Slide 22

Slide 22 text

objc_msgSend:"slow"path Used%once%per%unique%selector%per%class. • Method(is(not(cached.(Lookup(the(method(IMP(in(the(class(itself. • If(no(IMP(found,(try(to: • Resolve(methods(using(+resolveClassMethod(or( +resolveInstanceMethod. • Forward(using(forwarding(mechanism.

Slide 23

Slide 23 text

!Warning:!The!Objec*ve,C!run*me!lets!you!uncover!many! private!implementa*on!details!of!system!classes.!You!must!not!use! any!of!this!informa*on!in!your!final!product. !!"Technical"Note"TN2239""iOS"Debugging"Magic"

Slide 24

Slide 24 text

-[UIViewController attentionClassDumpUser:yesItsUsAga in:althoughSwizzlingAndOverridingP rivateMethodsIsFun:itWasntMuchFunW henYourAppStoppedWorking:pleaseRef rainFromDoingSoInTheFutureOkayThan ksBye:]

Slide 25

Slide 25 text

libextobjc Run$me'and'compiler'magic'at'its'best. …extends(the(dynamism(of(the(Objec4ve6C(programming(language( to(support(addi4onal(pa=erns(present(in(other(programming( languages((including(those(that(are(not(necessarily(object6oriented). !!"h$ps:/ /github.com/jspahrsummers/libextobjc.

Slide 26

Slide 26 text

@keypath Allows&compile,-me&verifica-on&of&key&paths. @interface MyClass : NSObject + (BOOL)classProperty; @property (nonatomic, assign) NSUInteger someUniqueProperty; @property (nonatomic, copy) NSArray /* MyClass */ *collection; @end @keypath(MyClass, classProperty); // @"classProperty" @collectionKeypath(obj.collection, MyClass.new, someUniqueProperty); // @"collection.someUniqueProperty"

Slide 27

Slide 27 text

@onExit Defines&some&code&to&be&executed&when&the¤t&scope&exits. __block BOOL cleanupBlockRun = NO; @try { @onExit { cleanupBlockRun = YES; }; [NSException raise:@"Wild exception" format:@"Absolutely unexpected"]; } @catch (NSException *exception) { // your recovery code } @finally { // cleanupBlockRun == YES }

Slide 28

Slide 28 text

EXTNil nil!value!you!can!add!to!collec-ons. NSDictionary *dictionary = @{@"foo":[EXTNil null]}; dictionary[@"foo"]; // [EXTNil null]; [(NSValue *)dictionary[@"foo"] CGRectValue]; // (CGRect){{0, 0}, {0, 0}}

Slide 29

Slide 29 text

Demo