.center.middle ## Cocoaheads Smalltalk # Tagged Pointers --- # Principe En 64-bit sur Intel, les pointeurs sont alignés sur 16 octets. .no-highlight 6 5 4 3 2 1 0 3210987654321098765432109876543210987654321098765432109876543210 ............................................................0000 --- # Principe En 64-bit sur Intel, les pointeurs sont alignés sur 16 octets. .no-highlight 6 5 4 3 2 1 0 3210987654321098765432109876543210987654321098765432109876543210 ........................................................ccccttt1 | | | +- 1 bit | | +---- 3 bits | +-------- 4 bits +---------------------------------------------------------------- 56 bits * 1 bit : flag, 1 pour les tagged pointers * 7 bits d'infos de type * 3 bits pour la classe Objective-C * 4 bits d'infos réservés pour la classe * 56 bits (7 octets) de payload --- # CFInternal.h .objectivec #define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1) #define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF) enum { kCFTaggedObjectID_Invalid = 0, kCFTaggedObjectID_Undefined0 = (0 << 1) + 1, kCFTaggedObjectID_Integer = (1 << 1) + 1, kCFTaggedObjectID_Undefined2 = (2 << 1) + 1, kCFTaggedObjectID_Undefined3 = (3 << 1) + 1, kCFTaggedObjectID_Undefined4 = (4 << 1) + 1, kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data kCFTaggedObjectID_Date = (6 << 1) + 1, kCFTaggedObjectID_DateTS = (7 << 1) + 1, }; --- # objc-private.h .objectivec #define OBJC_IS_TAGGED_PTR(PTR) ((uintptr_t)(PTR) & 0x1) extern Class _objc_tagged_isa_table[16]; static inline Class _object_getClass(id obj) { if (OBJC_IS_TAGGED_PTR(obj)) { uint8_t slotNumber = ((uint8_t) (uint64_t) obj) & 0x0F; Class isa = _objc_tagged_isa_table[slotNumber]; return isa; } } --- # Integers .objectivec - (void) testSanity { NSNumber * obj1 = [NSNumber numberWithInt:42]; NSNumber * obj2 = [NSNumber numberWithInt:42]; STAssertEqualObjects(obj1, obj2, @"both objects are equal"); } - (void) testPointerEquality { NSNumber * obj1 = [NSNumber numberWithInt:42]; NSNumber * obj2 = [NSNumber numberWithInt:42]; STAssertEquals(obj1, obj2, @"both objects are **the same**"); } - (void) testPointerValue { NSNumber * object = [NSNumber numberWithInt:42]; // shifting the last byte reveals the value STAssertEquals(42, (int)((long)object>>8), @"the value is in the pointer"); } --- # NSDate **NSDate <=> NSTimeInterval** .objectivec typedef union _DoubleOrPointer { NSTimeInterval interval; void * p; } DoubleOrPointer; - (void) testPointerValue { DoubleOrPointer dop = {.interval = 42.0}; NSDate * object = [NSDate dateWithTimeIntervalSinceReferenceDate: dop.interval]; // Masking out the last byte gives the passed interval STAssertEquals(dop.p, (void*)((long)object&0xFFFFFFFFFFFFFF00), @"the pointer is the value"); } --- # Links * objectivistc.tumblr.com * [Tagged pointers and fast-pathed CFNumber integers in Lion](http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in) * [A CHOCKING MYSTERY: po [NSNumber numberWithBool:NO] outputs 1](http://objectivistc.tumblr.com/post/8992822737/a-chocking-mystery-po-nsnumber-numberwithbool-no) * lists.apple.com * [Objc-langage](http://lists.apple.com/archives/Objc-language/2011/Nov/msg00014.html) * opensource.apple.com * [ObjC](http://opensource.apple.com/source/objc4/objc4-493.9/) * [CoreFoundation](http://opensource.apple.com/source/CF/CF-635/) --- # Bonus #1 : Singleton NSNumbers .objectivec - (void) testNSNumberSingletons { for (int i = -1000; i<=1000; i++) { // NSNumbers between -1 and 12 are singletons if(i>=-1 && i<=12) STAssertTrue( [NSNumber numberWithInt:i] == [NSNumber numberWithInt:i], @"objects should be the same pointer"); else STAssertTrue( [NSNumber numberWithInt:i] != [NSNumber numberWithInt:i], @"objects should not be the same pointer"); } } --- # Bonus #2 : objc4/runtime/hashtable2.m .objectivec /* hashtable2.m Copyright 1989-1996 NeXT Software, Inc. Created by Bertrand Serlet, Feb 89 */ ... /********************************************************************** * * On z'y va * **********************************************************************/ NXHashTable *NXCreateHashTable (NXHashTablePrototype prototype, ... --- .footnote[*Made with [remark](gnab.github.com/remark)*]