iOS_Class<Class>

class structure

  • A class Classis a objc_class *type of structure pointer,typedef struct objc_class *Class
  • Struct objc_classinherits from Structobjc_object
strcut 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() {
		return bits.data()
	}
	// 省略...
}
  • objc_objectContains one isa, so each class contains one isa, it can be said that everything is an object
strcut objc_object {
	Class _Nonnull isa OBJC_ISA_AVAILABILITY;
}
  • Structure cache_tpart code
struct cache_t { 
	struct buckrt_t *_buckets;
	mask_t _mask;
	mask_t _occupied;
	// 省略...
}

Attributes, instance methods, protocols, and class method storage

Property list, instance method list, and protocol list are all stored bitsinternally

  • The way to get the storage location of the attribute list: <similar to instance method/protocol>
    • bitsStep 1: Calculate the obtained address according to the first address and offset of the class
    • The second step: through bits.data()the obtained class_rw_t *pointera
    • Step 3: aYou can get class_ro_t *the pointer of the type through the pointerro
    • Step 4: ro.basePropertiesYou can get a property_list_t *type of pointer throughb
    • Step 5: Print the pointer b, you can see the attribute ( property) list
  • In addition, ro.ivarsyou can get a ivar_list_t *type of pointer cby printing the pointer c, and we can see the list of variables
  • By comparing the printed pointer bwith the pointer , it can be found that the attribute will compile a variable with a variable cin the variable list_
  • The class method is stored in the metaclass, you can get the class object first, then isaread the metaclass, and then search the method list in the metaclass according to the above method, you can get the class method list

Relevant structure code implementation

class_rw_tCode

struct class_rw_t {
	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;
#elseif
	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_ro_tCode

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

method_array_tCode

class method_array_t : 
    public list_array_tt<method_t, method_list_t> 
{
    typedef list_array_tt<method_t, method_list_t> Super;

 public:
    method_list_t **beginCategoryMethodLists() {
        return beginLists();
    }
    
    method_list_t **endCategoryMethodLists(Class cls);

    method_array_t duplicate() {
        return Super::duplicate<method_array_t>();
    }
};

property_array_tCode

class property_array_t : 
    public list_array_tt<property_t, property_list_t> 
{
    typedef list_array_tt<property_t, property_list_t> Super;

 public:
    property_array_t duplicate() {
        return Super::duplicate<property_array_t>();
    }
};

protocol_array_tCode

class protocol_array_t : 
    public list_array_tt<protocol_ref_t, protocol_list_t> 
{
    typedef list_array_tt<protocol_ref_t, protocol_list_t> Super;

 public:
    protocol_array_t duplicate() {
        return Super::duplicate<protocol_array_t>();
    }
};

list_array_ttCode

class list_array_tt {
    struct array_t {
        uint32_t count;
        List* lists[0];

        static size_t byteSize(uint32_t count) {
            return sizeof(array_t) + count*sizeof(lists[0]);
        }
        size_t byteSize() {
            return byteSize(count);
        }
    };

 protected:
    class iterator {
        List **lists;
        List **listsEnd;
        typename List::iterator m, mEnd;

     public:
        iterator(List **begin, List **end) 
            : lists(begin), listsEnd(end)
        {
            if (begin != end) {
                m = (*begin)->begin();
                mEnd = (*begin)->end();
            }
        }

        const Element& operator * () const {
            return *m;
        }
        Element& operator * () {
            return *m;
        }

        bool operator != (const iterator& rhs) const {
            if (lists != rhs.lists) return true;
            if (lists == listsEnd) return false;  // m is undefined
            if (m != rhs.m) return true;
            return false;
        }

        const iterator& operator ++ () {
            assert(m != mEnd);
            m++;
            if (m == mEnd) {
                assert(lists != listsEnd);
                lists++;
                if (lists != listsEnd) {
                    m = (*lists)->begin();
                    mEnd = (*lists)->end();
                }
            }
            return *this;
        }
    };

 private:
    union {
        List* list;
        uintptr_t arrayAndFlag;
    };

    bool hasArray() const {
        return arrayAndFlag & 1;
    }

    array_t *array() {
        return (array_t *)(arrayAndFlag & ~1);
    }

    void setArray(array_t *array) {
        arrayAndFlag = (uintptr_t)array | 1;
    }

 public:

    uint32_t count() {
        uint32_t result = 0;
        for (auto lists = beginLists(), end = endLists(); 
             lists != end;
             ++lists)
        {
            result += (*lists)->count;
        }
        return result;
    }

    iterator begin() {
        return iterator(beginLists(), endLists());
    }

    iterator end() {
        List **e = endLists();
        return iterator(e, e);
    }


    uint32_t countLists() {
        if (hasArray()) {
            return array()->count;
        } else if (list) {
            return 1;
        } else {
            return 0;
        }
    }

    List** beginLists() {
        if (hasArray()) {
            return array()->lists;
        } else {
            return &list;
        }
    }

    List** endLists() {
        if (hasArray()) {
            return array()->lists + array()->count;
        } else if (list) {
            return &list + 1;
        } else {
            return &list;
        }
    }

    void attachLists(List* const * addedLists, uint32_t addedCount) {
        if (addedCount == 0) return;

        if (hasArray()) {
            // many lists -> many lists
            uint32_t oldCount = array()->count;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
            array()->count = newCount;
            memmove(array()->lists + addedCount, array()->lists, 
                    oldCount * sizeof(array()->lists[0]));
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0]));
        }
        else if (!list  &&  addedCount == 1) {
            // 0 lists -> 1 list
            list = addedLists[0];
        } 
        else {
            // 1 list -> many lists
            List* oldList = list;
            uint32_t oldCount = oldList ? 1 : 0;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)malloc(array_t::byteSize(newCount)));
            array()->count = newCount;
            if (oldList) array()->lists[addedCount] = oldList;
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0]));
        }
    }

    void tryFree() {
        if (hasArray()) {
            for (uint32_t i = 0; i < array()->count; i++) {
                try_free(array()->lists[i]);
            }
            try_free(array());
        }
        else if (list) {
            try_free(list);
        }
    }

    template<typename Result>
    Result duplicate() {
        Result result;

        if (hasArray()) {
            array_t *a = array();
            result.setArray((array_t *)memdup(a, a->byteSize()));
            for (uint32_t i = 0; i < a->count; i++) {
                result.array()->lists[i] = a->lists[i]->duplicate();
            }
        } else if (list) {
            result.list = list->duplicate();
        } else {
            result.list = nil;
        }

        return result;
    }
};

Guess you like

Origin blog.csdn.net/FlyingKuiKui/article/details/120934102