iOS underlying principle - isa principle

isa initialization

isa structure

  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

};

Thus be seen isa a consortium, a data type, the 8 bytes occupied. It features: shared memory, or with exclusive features, meaning that the assignment of cls, not to other members of the assignment. Wherein ISA_BITFIELD is a macro definition, it is a bit field, which defines the following structure

 

#if SUPPORT_PACKED_ISA

 

    // extra_rc must be the MSB-most field (so it matches carry/overflow flags)

    // nonpointer must be the LSB (fixme or get rid of it)

    // shiftcls must occupy the same bits that a real class pointer would

    // bits + RC_ONE is equivalent to extra_rc + 1

    // RC_HALF is the high bit of extra_rc (i.e. half of its range)

 

    // future expansion:

    // uintptr_t fast_rr : 1;     // no r/r overrides

    // uintptr_t lock : 2;        // lock for atomic property, @synch

    // uintptr_t extraBytes : 1;  // allocated with extra bytes

 

# 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__

#   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)

 

# else

#   error unknown architecture for packed isa

# endif

 

// SUPPORT_PACKED_ISA

#endif

 

 

#if SUPPORT_INDEXED_ISA

 

# if  __ARM_ARCH_7K__ >= 2  ||  (__arm64__ && !__LP64__)

    // armv7k or arm64_32

 

#   define ISA_INDEX_IS_NPI_BIT  0

#   define ISA_INDEX_IS_NPI_MASK 0x00000001

#   define ISA_INDEX_MASK        0x0001FFFC

#   define ISA_INDEX_SHIFT       2

#   define ISA_INDEX_BITS        15

#   define ISA_INDEX_COUNT       (1 << ISA_INDEX_BITS)

#   define ISA_INDEX_MAGIC_MASK  0x001E0001

#   define ISA_INDEX_MAGIC_VALUE 0x001C0001

#   define ISA_BITFIELD                         \

      uintptr_t nonpointer        : 1;          \

      uintptr_t has_assoc         : 1;          \

      uintptr_t indexcls: 15; \

      uintptr_t magic             : 4;          \

      uintptr_t has_cxx_dtor      : 1;          \

      uintptr_t weakly_referenced : 1;          \

      uintptr_t deallocating      : 1;          \

      uintptr_t has_sidetable_rc  : 1;          \

      uintptr_t extra_rc          : 7

#   define RC_ONE   (1ULL<<25)

#   define RC_HALF  (1ULL<<6)

 

# else

#   error unknown architecture for indexed isa

# endif

 

// SUPPORT_INDEXED_ISA

#endif

isa arm64 arguments detailed:

nonpointer: indicates whether to turn on isa pointer to optimize 0: pure isa pointer, 1: not only is the class object address, isa contains the class information, reference counting objects
has_assoc: associated object flag 0 no 1 is present
has_cxx_dtor: whether the object has Objc or C ++ destructor, if destructor, destructor logic needed to be done, and if not, the object is released faster
shiftcls:
value storing pointer to a class. Open pointer optimization case, there are 33 classes to store pointers arm64 architecture.
magic: a debugger to determine the current object or objects is really no room for initialization weakly_referenced: Chi whether the object is a point to point or ARC had weak variables,
objects no weak references can be released faster. deallocating: flag whether the object is freeing memory
has_sidetable_rc: When the object reference technology is greater than 10, then the need to borrow the variable storage carry
extra_rc: when indicates reference count of the object actually reference count is decremented by 1, e.g., if the object the reference count is 10, then extra_rc 9. If the reference count is greater than 10, it is necessary to use the following has_sidetable_rc.

Isa point of analysis

  1. Associated with an object class
    LGPerson * object = [LGPerson alloc] ;

Brief lldb command

information memory section 4 x / 4gx objc objc of printing. Extended: x / 6gx is to print information memory section 6.
p / tp / t binary print information; p / o octal print information; p / x hexadecimal print information; p / d print decimal information, where the print information memory section 4, a first object property must be ISA, because it is inherited from NSObject,

@interface NSObject <NSObject> {

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Wobjc-interface-ivars"

    Class isa  OBJC_ISA_AVAILABILITY;

#pragma clang diagnostic pop

}

 

Return to the topic, by object_getClass (object); find related information

Class object_getClass(id obj)

{

    if (obj) return obj->getIsa();

    else return Nil;

}

 

objc_object::getIsa() 

{

    if (!isTaggedPointer()) return ISA();

 

    uintptr_t ptr = (uintptr_t)this;

    if (isExtTaggedPointer()) {

        uintptr_t lock = 

            (ptr >> _OBJC_TAG_EXT_SLOT_SHIFT) & _OBJC_TAG_EXT_SLOT_MASK;

        return objc_tag_ext_classes[slot];

    } else {

        uintptr_t lock = 

            (ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_SLOT_MASK;

        return objc_tag_classes[slot];

    }

}

 

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

}

 

Analysis of the source can be seen from the last class is returned (Class) (isa.bits & ISA_MASK) results, and then start the verification, as follows, which proves the point isa class:

 
Screenshot 2.50.55.png 2020-02-09 PM

Analytical object number memory exists

We know that you can create multiple objects, the class does, whether it can create more, now verify:

 

 

Class class1 = [LGPerson class];

    Class class2 = [LGPerson alloc].class;

    Class class3 = object_getClass([LGPerson alloc]);

    Class class4 = [LGPerson alloc].class;

    NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);

 

The output is

2020-02-1000: 27: 37.559203 + 0800001- objects isa [7942: 604270] 

0x100002400-

0x100002400-

0x100002400-

0x100002400

Proof can only create a class, only one in memory inside

isa walk & inheritance

As can be seen from the object points to the class isa Through the above analysis, and then continues to walk analyzed according to FIG isa

 
 
isa flowchart .png

虚线代表了isa的走位。实例对象->类->元类->根元类->根根元类(根元类本身)。
实线代表了继承关系。这里值得注意的就是根元类的父类是NSObject,NSObject父类是nil。
开始验证:
1.isa从对象指向类

XDPerson *person = [XDPerson alloc];

 

(lldb) x/4gx person

0x10185eac0: 0x001d8001000011a9 0x0000000000000000

0x10185ead0: 0x000000010185eba0 0x000000010185ede0

(lldb) p/x 0x001d8001000011a9 & 0x0000000ffffffff8

(long) $1 = 0x00000001000011a8

(lldb) po $1

XDPerson

 

2.isa从类指向元类

(lldb) x/4gx $1

0x1000011a8: 0x001d800100001181 0x00000001000011f8

0x1000011b8: 0x00000001003a1e50 0x0000000000000000

(lldb) p/x 0x001d800100001181 & 0x0000000ffffffff8

(long) $2 = 0x0000000100001180

(lldb) po $2

XDPerson

 

我们打印类XDPerson的内存信息,通过类的isa&ISA_MASK获取到了另外一个类的信息。即isa从类XDPerson又指向了类XDPerson(其实这个类是我们XDPerson的metaClass元类,它与第一步的XDPerson的内存地址并不同)。
3.isa从元类指向根元类

 

(lldb) x/4gx $2

0x100001180: 0x001d800100aff0f1 0x00000001000011d0

0x100001190: 0x0000000101e142b0 0x0000000100000007

(lldb) p/x 0x001d800100aff0f1 & 0x0000000ffffffff8

(long) $3 = 0x0000000100aff0f0

(lldb) po $3

NSObject

我们打印元类XDPerson的内存信息 通过元类的isa & ISA_MASK 获取到了另外一个元类类NSObject的信息。即isa从元类XDPerson又指向了元类NSObject。这里我们可以来打印NSObjcr.class来观察,元类NSObject的内存地址NSObjcr.class的内存地址并不同。

4.isa从根元类指向根根元类

(lldb) x/4gx $3

0x100aff0f0: 0x001d800100aff0f1 0x0000000100aff140

0x100aff100: 0x0000000101e146e0 0x0000000300000007

(lldb) p/x 0x001d800100aff0f1 & 0x0000000ffffffff8

(long) $4 = 0x0000000100aff0f0

(lldb) po $4

NSObject

 

这里补充一下几个概念
对象 是程序员根据类实例化出来的
类 是代码写出来的,内存中只有一份,是系统创建的
元类 是系统编译的,发现有了这么一个类 - 系统也同时创建了
方法 是编译阶段产生的

Guess you like

Origin www.cnblogs.com/cui-cui/p/12289655.html