OC中类的源码
#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif
/// 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
objc_object 源码
struct objc_object {
private:
isa_t isa;
public:
......
}
isa_t 源码
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
#if defined(ISA_BITFIELD)
struct {
ISA_BITFIELD; // defined in isa.h
};
#endif
};
objc_class 源码
objc_class
继承自objc_object
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
.......
}
isa指针
isa指针.pngisa指针是什么含义?
指针型isa和非指针型isa,非指针型只有前30-40多位用来代表Class
的地址,在寻址过程中只寻找30-40位的地址,就保证了我们可以寻找到想要的Class
的地址,多出来的可以用来存储其他的相关内容,这样做可以达到一个节省内存的目的。
isa指向
isa指向.png- 实例在OC中对应的就是
id
类型,表述在runtime中对应的就是objc_object
,objc_object
当中一个isa指针,对于实例来说他的isa指针指向他对应的Class
(类对象) -
Class
在runtime中对应的是objc_class
,objc_class
又继承自objc_object
,所以说Class也是一种对象,称之为类对象,由于继承自objc_object
所以也有一个isa指针,这个指针指向的是元类对象。 - 在进行方法调用的时候,在调用实例的实例方法时,实际上是通过isa指针到类对象当中去进行方法查找,如果调用的是一个类方法,通过类对象的isa指针到元类对象中进行方法的查找。
cache_t
-
用于快速查找方法执行函数
-
是可增量扩展的哈希表结构
当结构所存储的量在增大的过程中,他会增量的扩大他的内存空间,来支持更多的缓存。用哈希表来实现数据结构,主要是为了提高查找效率
-
是局部性原理的最佳应用
局部性原理是指计算机在执行某个程序时,倾向于使用最近使用的数据。局部性原理有两种表现形式:时间局部性和空间局部性。
时间局部性是指被引用过的存储器位置很可能会被再次引用,例如:重复的引用一个变量时则表现出较好的时间局部性
空间局部性是指被引用过的存储器位置附近的数据很可能将被引用;例如:遍历二维数组时按行序访问数据元素具有较好的空间局部性
cache_t源码
struct bucket_t {
private:
// IMP-first is better for arm64e ptrauth and no worse for arm64.
// SEL-first is better for armv7* and i386 and x86_64.
#if __arm64__
MethodCacheIMP _imp; //无类型的函数指针
cache_key_t _key; //方法选择器
#else
cache_key_t _key;
MethodCacheIMP _imp;
#endif
public:
inline cache_key_t key() const { return _key; }
inline IMP imp() const { return (IMP)_imp; }
inline void setKey(cache_key_t newKey) { _key = newKey; }
inline void setImp(IMP newImp) { _imp = newImp; }
void set(cache_key_t newKey, IMP newImp);
};
struct cache_t {
struct bucket_t *_buckets;
mask_t _mask;
mask_t _occupied;
public:
struct bucket_t *buckets();
mask_t mask();
mask_t occupied();
void incrementOccupied();
void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask);
void initializeToEmpty();
mask_t capacity();
bool isConstantEmptyCache();
bool canBeFreed();
static size_t bytesForCapacity(uint32_t cap);
static struct bucket_t * endMarker(struct bucket_t *b, uint32_t cap);
void expand();
void reallocate(mask_t oldCapacity, mask_t newCapacity);
struct bucket_t * find(cache_key_t key, id receiver);
static void bad_cache(id receiver, SEL sel, Class isa) __attribute__((noreturn));
};
cache_t结构.png
class_data_bits_t
-
class_data_bits_t
主要是对class_rw_t
的封装 -
class_rw_t
代表了类相关的读写信息、对class_ro_t
的封装class_rw_t
给类添加的一些分类当中的方法,属性,或者协议,都是在这个数据结构当中 -
class_ro_t
代表了类相关的只读信息。
源码
class_data_bits_t
struct class_data_bits_t {
// Values are the FAST_ flags above.
uintptr_t bits;
private:
bool getBit(uintptr_t bit)
{
return bits & bit;
}
.........
public:
class_rw_t* data() {
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;
uint32_t version;
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
void setFlags(uint32_t set)
{
OSAtomicOr32Barrier(set, &flags);
}
void clearFlags(uint32_t clear)
{
OSAtomicXor32Barrier(clear, &flags);
}
// set and clear must not overlap
void changeFlags(uint32_t set, uint32_t clear)
{
assert((set & clear) == 0);
uint32_t oldf, newf;
do {
oldf = flags;
newf = (oldf | set) & ~clear;
} while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
}
};
图形结构
class_rw_t.pngclass_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;
method_list_t *baseMethods() const {
return baseMethodList;
}
};
图形结构展示
class_ro_t.pngro意为readOnly,即类本身拥有的东西,已经完成后续不会再增加删除,所以使用了一维数组存储。
method_t源码实现
struct method_t {
SEL name;
const char *types;
MethodListIMP imp;
struct SortBySELAddress :
public std::binary_function<const method_t&,
const method_t&, bool>
{
bool operator() (const method_t& lhs,
const method_t& rhs)
{ return lhs.name < rhs.name; }
};
};
函数与method_t的关系
method_t.pngType Encodings
const char* types
网友评论