-
Notifications
You must be signed in to change notification settings - Fork 53
类与对象
jiaxw32 edited this page Jun 6, 2020
·
4 revisions
typedef struct objc_object *id;
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
-
objc_class
typedef struct objc_class *Class; struct objc_class : objc_object { // Class ISA; Class superclass; cache_t cache; // formerly cache pointer and vtable class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags class_rw_t *data() const { return bits.data(); } void setData(class_rw_t *newData) { bits.setData(newData); } ... }
-
class_data_bits_t
class_data_bits_t is the class_t->data field (class_rw_t pointer plus flags). The extra bits are optimized for the retain/release and alloc/dealloc paths.
struct class_data_bits_t { friend objc_class; // Values are the FAST_ flags above. uintptr_t bits; ... public: class_rw_t* data() const { return (class_rw_t *)(bits & FAST_DATA_MASK); } void setData(class_rw_t *newData) { ASSERT(!data() || (newData->flags & (RW_REALIZING | RW_FUTURE))); // Set during realization or construction only. No locking needed. // Use a store-release fence because there may be concurrent // readers of data and data's contents. uintptr_t newBits = (bits & ~FAST_DATA_MASK) | (uintptr_t)newData; atomic_thread_fence(memory_order_release); bits = newBits; } }
-
class_rw_t
struct class_rw_t { // Be warned that Symbolication knows the layout of this structure. uint32_t flags; uint16_t version; uint16_t witness; const class_ro_t *ro; method_array_t methods; property_array_t properties; protocol_array_t protocols; Class firstSubclass; Class nextSiblingClass; char *demangledName; #if SUPPORT_INDEXED_ISA uint32_t index; #endif
-
class_ro_t
struct class_ro_t { uint32_t flags; uint32_t instanceStart; uint32_t instanceSize; #ifdef __LP64__ uint32_t reserved; #endif const uint8_t * ivarLayout; const char * name; method_list_t * baseMethodList; protocol_list_t * baseProtocols; const ivar_list_t * ivars; const uint8_t * weakIvarLayout; property_list_t *baseProperties; ... }
typedef struct property_t *objc_property_t;
struct property_t {
const char *name;
const char *attributes;
};
/// Defines a property attribute
typedef struct {
const char *name; /**< The name of the attribute */
const char *value; /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;
struct property_list_t : entsize_list_tt<property_t, property_list_t, 0> {
};
/// An opaque type that represents an instance variable.
typedef struct ivar_t *Ivar;
struct ivar_t {
#if __x86_64__
// *offset was originally 64-bit on some x86_64 platforms.
// We read and write only 32 bits of it.
// Some metadata provides all 64 bits. This is harmless for unsigned
// little-endian values.
// Some code uses all 64 bits. class_addIvar() over-allocates the
// offset for their benefit.
#endif
int32_t *offset;
const char *name;
const char *type;
// alignment is sometimes -1; use alignment() instead
uint32_t alignment_raw;
uint32_t size;
};
struct ivar_list_t : entsize_list_tt<ivar_t, ivar_list_t, 0> {
bool containsIvar(Ivar ivar) const {
return (ivar >= (Ivar)&*begin() && ivar < (Ivar)&*end());
}
};
typedef struct method_t *Method;
struct method_t {
SEL name;
const char *types;
MethodListIMP imp;
};
// Two bits of entsize are used for fixup markers.
struct method_list_t : entsize_list_tt<method_t, method_list_t, 0x3> {
bool isUniqued() const;
bool isFixedUp() const;
void setFixedUp();
uint32_t indexOfMethod(const method_t *meth) const {
uint32_t i =
(uint32_t)(((uintptr_t)meth - (uintptr_t)this) / entsize());
ASSERT(i < count);
return i;
}
};
/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;
/// A pointer to the function of a method implementation.
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ );
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
#endif
-
Person
对象内存结构(lldb) po [personA _ivarDescription] <Person: 0x60000377d9e0>: in Person: _name (NSString*): nil _age (long): 0 in NSObject: isa (Class): Person (isa, 0x10e8b36f0)
Person
实例对象personA
的isa
指针指向Person
类 -
Person
类内存结构(lldb) memory read --size 8 --format x --count 2 0x10e8b36f0 0x10e8b36f0: 0x000000010e8b36c8(Person 类 isa,指向元类) 0x00007fff89be2d00 (Person 类父类,指向 NSObject)
-
Person
父类(lldb) p/x class_getSuperclass([person class]) (Class) $120 = 0x00007fff89be2d00 NSObject
0x00007fff89be2d00
为Person
父类NSObject
,与上面读取的地址相同 -
Person
元类,内存结构(lldb) memory read --size 8 --format x --count 2 0x000000010e8b36c8 0x10e8b36c8: 0x00007fff89be2cd8(Person 元类 isa,指向 NSObject 元类) 0x00007fff89be2cd8(Person 元类父类,指向 NSObject 元类)
Person
元类的isa
与super_class
都指向NSObject
的元类0x00007fff89be2cd8
-
NSObject
内存结构(lldb) memory read --size 8 --format x --count 2 0x00007fff89be2d00 0x7fff89be2d00: 0x00007fff89be2cd8(NSObject isa 指向元类) 0x0000000000000000(NSOjbect 父类指向 nil)
-
NSObject
元类内存结构(lldb) memory read --size 8 --format x --count 2 0x00007fff89be2cd8 0x7fff89be2cd8: 0x00007fff89be2cd8(NSObject 元类 isa 指向自身) 0x00007fff89be2d00(NSOjbect 元类的父类指向 NSObject 类)