inOC principle — The nature of objects and classesAs mentioned in this article, it takes a bit operation on the ISA pointer to get the real addresses of class and meta-class objects.

  • Before 64-bit, ISA is just a pointer that stores the memory address of the class object, the meta-class object.
  • Since 64-bit, ISA has been optimized to become oneCommon body (Union) structureDifferent bit fields are used to store different information

From the figure above we can also see that isa isa Commons structure.

union isa_t { Class cls; uintptr_t bits; // isa is 64 bits (8 bytes); the first bit on the right holds nonpointer; the second bit on the right holds has_assoc... It takes only 8 bytes to store that much information. Struct {ISA_BITFIELD}; }; # if __arm64__ # define ISA_MASK 0x0000000ffffffff8ULL # define ISA_MAGIC_MASK 0x000003f000000001ULL # define ISA_MAGIC_VALUE 0x000001a000000001ULL # define ISA_BITFIELD uintptr_t nonpointer : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ uintptr_t magic : 6; uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 19 # define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18) # elif __x86_64__ // Simulator macOS application # define ISA_MASK 0x00007ffffffffff8ULL # define ISA_MAGIC_MASK 0x001f800000000001ULL # define ISA_MAGIC_VALUE 0x001d800000000001ULL # define ISA_BITFIELD uintptr_t nonpointer : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \ uintptr_t magic : 6; uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 8 # define RC_ONE (1ULL<<56) # define RC_HALF (1ULL<<7) # endifCopy the code

We see that nine bits of information are stored in isa and only eight bytes (64 bits) are used. This is the advantage of sharing. We can extract information from different bit fields through masks. Our ios development needs to focus on the ARM64 case

  • nonpointer
    • 0: indicates a common pointer that stores the memory address of Class and meta-class objects
    • 1: indicates that it has been optimized. Different bit fields are used to store different information
  • has_assoc
    • Is the associated object set? If not, it will be released faster
  • has_cxx_dtor
    • Is there a C++ destructor? If not, it will be released faster
  • shiftcls
    • The memory addresses where Class and meta-class objects are stored are also explained here& ISA_MASKTo obtain the memory address of Class and meta-class objects
  • magic
    • Used during debugging to tell if an object is initialized
  • weakly_referenced
    • Is there a weak reference pointing to it? If not, it will be released faster
  • deallocating
    • Whether the object is being released
  • extra_rc
    • The value stored inside is the reference count minus 1
  • has_sidetable_rc
    • 0: The reference count is stored in the extra_R bitfield of ISA

    • 1: The reference count is too large to be stored in ISA. The reference count is stored in an attribute of a class called SideTable

Objc_destructInstance is called when the object is freed

void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        if (cxx) object_cxxDestruct(obj);
        if (assoc) _object_remove_assocations(obj);
        obj->clearDeallocating();
    }

    return obj;
}
Copy the code

We see faster object release with no destructor and no associated object set.