iOS内存管理方案

__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;
        }
    }
};

你可能感兴趣的:(iOS内存管理方案)