__x86_64__环境调试
TaggedPointer
解析
判断
static inline bool
_objc_isTaggedPointer(const void * _Nullable ptr)
{
return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
ptr&(1UL) == 1UL
取值
value = (ptr^objc_debug_taggedpointer_obfuscator)>>8
NONPOINTER_ISA
解析
判断class指针==isa
inline Class
objc_object::ISA()
{
ASSERT(!isTaggedPointer());
#if SUPPORT_INDEXED_ISA
if (isa.nonpointer) {
uintptr_t slot = isa.indexcls;
return classForIndex((unsigned)slot);
}
return (Class)isa.bits;
#else
return (Class)(isa.bits & ISA_MASK);
#endif
}
取值
(lldb) p/x ob.class
(Class) $22 = 0x00007fff8e578118 NSObject
(lldb) p/x ob->isa
(Class) $21 = 0x001dffff8e578119 NSObject
0000 0000 extra_rc
0 has_sidetable_rc
0 deallocating
0 weakly_referenced
1 1101 1 magic
111 1111 1111 1111 1000 1110 0101 0111 1000 0001 0001 1 shiftcls
0 has_cxx_dtor
0 has_assoc
1 nonpointer
shiftcls计算出类对象地址
初始化isa
inline void
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor)
{
ASSERT(!isTaggedPointer());
if (!nonpointer) {
isa = isa_t((uintptr_t)cls);
} else {
ASSERT(!DisableNonpointerIsa);
ASSERT(!cls->instancesRequireRawIsa());
isa_t newisa(0);
#if SUPPORT_INDEXED_ISA
ASSERT(cls->classArrayIndex() > 0);
newisa.bits = ISA_INDEX_MAGIC_VALUE;
// isa.magic is part of ISA_MAGIC_VALUE
// isa.nonpointer is part of ISA_MAGIC_VALUE
newisa.has_cxx_dtor = hasCxxDtor;
newisa.indexcls = (uintptr_t)cls->classArrayIndex();
#else
newisa.bits = ISA_MAGIC_VALUE;
// isa.magic is part of ISA_MAGIC_VALUE
// isa.nonpointer is part of ISA_MAGIC_VALUE
newisa.has_cxx_dtor = hasCxxDtor;
newisa.shiftcls = (uintptr_t)cls >> 3;
#endif
// This write must be performed in a single store in some cases
// (for example when realizing a class because other threads
// may simultaneously try to use the class).
// fixme use atomics here to guarantee single-store and to
// guarantee memory order w.r.t. the class index table
// ...but not too atomic because we don't want to hurt instantiation
isa = newisa;
}
}
左移三位得到cls指针
11111111111111110001110010101111000000100011<<3
>>> hex(int('11111111111110001110010101111000000100011000', 2))
'0xfff8e578118'
散列表
SideTable
struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;
SideTable() {
memset(&weak_table, 0, sizeof(weak_table));
}
~SideTable() {
_objc_fatal("Do not delete SideTable.");
}
void lock() { slock.lock(); }
void unlock() { slock.unlock(); }
void forceReset() { slock.forceReset(); }
// Address-ordered lock discipline for a pair of side tables.
template
static void lockTwo(SideTable *lock1, SideTable *lock2);
template
static void unlockTwo(SideTable *lock1, SideTable *lock2);
};
RefcountMap
template ,
typename KeyInfoT = DenseMapInfo,
typename BucketT = detail::DenseMapPair>
class DenseMap : public DenseMapBase,
KeyT, ValueT, ValueInfoT, KeyInfoT, BucketT> {
friend class DenseMapBase;
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
using BaseT = DenseMapBase;
BucketT *Buckets;
unsigned NumEntries;
unsigned NumTombstones;
unsigned NumBuckets;
....
BucketT
namespace detail {
// We extend a pair to allow users to override the bucket type with their own
// implementation without requiring two members.
template
struct DenseMapPair : public std::pair {
// FIXME: Switch to inheriting constructors when we drop support for older
// clang versions.
// NOTE: This default constructor is declared with '{}' rather than
// '= default' to work around a separate bug in clang-3.8. This can
// also go when we switch to inheriting constructors.
DenseMapPair() {}
DenseMapPair(const KeyT &Key, const ValueT &Value)
: std::pair(Key, Value) {}
DenseMapPair(KeyT &&Key, ValueT &&Value)
: std::pair(std::move(Key), std::move(Value)) {}
template
DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue,
typename std::enable_if<
std::is_convertible::value &&
std::is_convertible::value>::type * = 0)
: std::pair(std::forward(AltKey),
std::forward(AltValue)) {}
template
DenseMapPair(AltPairT &&AltPair,
typename std::enable_if>::value>::type * = 0)
: std::pair(std::forward(AltPair)) {}
KeyT &getFirst() { return std::pair::first; }
const KeyT &getFirst() const { return std::pair::first; }
ValueT &getSecond() { return std::pair::second; }
const ValueT &getSecond() const { return std::pair::second; }
};
} // end namespace detail
weak_table_t
struct weak_table_t {
weak_entry_t *weak_entries;
size_t num_entries;
uintptr_t mask;
uintptr_t max_hash_displacement;
};
weak_entry_t
struct weak_entry_t {
DisguisedPtr referent;
union {
struct {
// 这里要存储的是一个weak指针数组,所以采用哈希算法
weak_referrer_t *referrers; // 指向referent对象的weak指针数组
uintptr_t out_of_line_ness : 2; // 这里标记是否超过内联边界
uintptr_t num_refs : PTR_MINUS_2; // 数组中已占用的大小
uintptr_t mask; // 数组下标最大值(数组大小-1)
uintptr_t max_hash_displacement; // 最大哈希偏移值
};
struct {
// out_of_line_ness field is low bits of inline_referrers[1]
weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];
};
};
bool out_of_line() {
return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
}
weak_entry_t& operator=(const weak_entry_t& other) {
memcpy(this, &other, sizeof(other));
return *this;
}
weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
: referent(newReferent)
{
inline_referrers[0] = newReferrer;
for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
inline_referrers[i] = nil;
}
}
};