To learn the nature of objects, first introduce the tool Clang

A,Clang

1. What isClang

Clang is a lightweight compiler for C, C++, and Objective-C. Source code is published under the BSD protocol. Clang will support its normal lambda expressions, simplified handling of return types, and better handling of constEXPr keywords.

Clang is an Apple-led, LLVM-based C/C++/Objective-C compiler

In April 2013,Clang fully supported the C++11 standard and began implementing C++1y features (i.e. C++14, the next minor update to C++). Clang will support its normal lambda expressions, simplified handling of return types, and better handling of constEXPr keywords.

Clang is a C/C++/Objective-C/ Objective-C++ compiler written in C++, based on LLVM and published under the LLVM BSD license. It is almost completely compatible with the GNU C language specification (although there are some incompatibables, including some differences in compiler command options) and adds additional syntactical features such as C function overloading (which modifies functions by __attribute__((overloadable)), One of its goals is to go beyond GCC.

2. ClangThe use of

Clang-rewrite-objc main.m -o main. CPP compiles the object file into a c++ file

  • UIKit reported an error

Clang-rewrite-objc-fobjc-arc-fobjc-runtime =ios-13.0.0 -isysroot / Applications/Xcode. App/Contents/Developer/Platforms/iPhoneSimulator platform/Developer/SDKs/iPhoneSimulator13.0. The SDK main.m

  • xcodeI installed it along the wayxcrunCommand,xcrunCommand inclangOn the basis of some encapsulation, to better use some

Xcrun – SDK iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

Xcrun – SDK iphoneOS clang -arch arm64 – rerewrite -objc main.m -o main-arm64.cpp

Ii. Is the underlying nature of the object of inquiry a structure?

1. LGPersonObject analysis

Create a custom object LGPerson in main.m with a property KCName

Go to the terminal of the main.m directory and run the clang-rewrite-objc main.m -o main. CPP command to compile the main.m file into the main. CPP file. Open the compiled main. CPP source file and find the definition of LGPerson. LGPerson is compiled into struct structures underneath

Results analysis:

  1. LGPersonThe bottom isThe structure of the body
  2. LGPerson_IMPLThe first property in theisaIs inherited fromNSObject, belong toPseudo inheritancePseudo-inheritedwayIs directly to theNSObjectThe structure is defined asLGPersonIn theThe first propertyThat means thatLGPersonhaveNSObjectIn theAll member variables.
  3. LGPersonThe first property inNSObject_IVARSEquivalent toNSObjectIn theisa

2. NSObjectAnalysis of the

Source code analysis:

  1. NSObjectPoint to the samestruct objc_object
  2. NSObjectIn the structure, there areClassType of a member variableisa

3. ClassAnalysis of the underlying nature of types

Isa is of type Class and is defined as a structure pointer to objc_class. Id is used to represent any object in development because ID is defined as a pointer to objC_Object, and hence to NSObject.

4. get/setmethods

Through source code analysis can be sent, whether getorset, contain hidden parameters. The current value is obtained from the first address of the current object + the offset value of the variable.

conclusion

The essence of the object is that the isa of the structure LGPerson is inherited from the ISA in NSObject where there’s only one member variable ISA

Three, the commonwealth bit domain

Before learning about ISA, understand the union bit field. Why is isa defined as a union type isa_t

Case analysis, introducing a structural analysis

struct LGCar1 {
    BOOL front; // 0 1
    BOOL back;
    BOOL left;
    BOOL right;
};
Copy the code

If you look at the print result, the current structure occupies 4 bytes and occupies 32 bits. Using 4 bytes to withdraw a single function wastes 3 times the space.

The improvements are as follows:

Struct LGCar2 {BOOL front: 1; BOOL back : 1; BOOL left : 1; BOOL right: 1; };Copy the code

BOOL front: 1 indicates the use of 1 bit, so LGCar2 needs only 4 bits, 1 byte to meet the requirement, 0000 1111

1. The structurestructCharacteristic analysis

The current structure takes up 24 bytes. The structure must be an integer multiple of the largest internal member.

variable Take up the byte offset min location
char *name 8 0 min(0, 8) 0 ~ 7
int age 4 8 min(8, 4) 8 ~ 11
double height 8 16 min(16, 8) 16 to 24

At the beginning, all member variables are assigned with empty values, and the execution is completed. Both member variables can be assigned at the same time, and they are in the coexistence state.

2. The commonwealth ofunionCharacteristics analysis

// union: mutually exclusive LGTeacher2 {char *name; int age; double height ; };Copy the code

According to the print analysis, only one union can be used

On the first print, all the fields are 0. On the second print, the name field is assigned, but none of the other fields are 0 because the other fields are not used (dirty data, dirty memory). On the third print, the age field is assigned, the name field is empty, and only one union can be used

3. Summary and analysis

The structure of the body

A struct is a combination of different pieces of data into a whole, in which variables coexist and are allocated memory regardless of whether they are used or not.

  • Advantages: Storage is large and inclusive, and members do not interact with each other

  • Disadvantages: Struct memory allocation is extensive, no use, all attributes are allocated memory. It’s a waste, so let’s say you have 4 BOOL members, you allocate 4 bytes of memory, but when you use it, you only use 1 byte, and the remaining 3 bytes are a waste of memory

A consortium

Unions are also composed of different data types, but their variables are mutually exclusive, and all the members occupy a total memory segment. Moreover, the common body adopts the memory overwrite technology, which can only store the value of one member at a time. If a value is assigned to a new member, the value of the original member will be overwritten

  • Advantages: All members share a segment of memory, which makes memory usage more delicate and flexible and saves memory space
  • Bad: Not “inclusive” enough

The difference between the two

  • Memory usage

    • Structure of theEach member occupies different memoryBetween each otherHave no effect on
    • Share bodyAll members occupy the same memory segment, modify a member willimpactAll remaining members
  • Memory allocation size

    • Structure in vivo> =All members occupiedThe sum of memory(There may be gaps between members)
    • The appropriateThe amount ofmemoryIs equal to theLargest memberThe amount ofmemory

Four,isaAnalysis of the

1. isaThe type ofisa_t

The isa pointer type isa_t is defined by union

// Combine isa_t() {} isa_t(uintptr_t value) : bits(value) {} uintptr_t bits; #if defined(ISA_BITFIELD) struct { ISA_BITFIELD; // defined in isa.h }; #endif };Copy the code

The reason for the use of union for the ISA_t type is also based on memory optimization, where the ISA pointer takes up 8 bytes of memory

As can be seen from the definition of ISA_T:

  • It provides two member variables, CLS and bits, which are mutually exclusive.

  • The struct member ISA_BITFIELD, which is a macro definition, has two versions __arm64__ (iOS mobile) and __x86_64__ (macOS). Their macro definition is shown below

  • Nonpointer: indicates whether pointer optimization is enabled for isa Pointers

    • 0: pureisaPointer to the
    • 1: Not only class object address,isaContains class information, object reference counts, and so on
  • Has_assoc: associated object flag bit

    • 0: There is noassociations
    • 1: There areassociations
  • Has_cxx_dtor: whether this object has a destructor for C++ or Objc

    • ifThere areDestructor, then need to do the destructor logic
    • ifThere is no, the object can be released faster
  • Shiftcls: Stores the value of a class pointer, that is, information about the class

    • 33 bits in ARM64. With pointer optimization enabled, 33 bits are used to store class Pointers in the ARM64 architecture.
    • The value contains 44 bits in x86_64
  • Magic: Used by the debugger to determine whether the current object is a real object or has no space to initialize

  • Weakly_referenced: A weak variable that records whether an object is pointed to or used to point to an ARC. Objects without weak references can be released faster.

  • Deallocating: Indicates whether the object is freeing memory

  • Has_sidetable_rc: When the object reference technique is greater than 10, this variable is borrowed to store carry

  • Extra_rc: When representing the reference count value of this object, which is actually the reference count value minus 1,

    • For example, if the object’s reference count is 10, extra_rc is 9. If the reference count is greater than 10, the following has_sideTABLE_rc is used.

For the two different platforms, the storage of isa is shown in the figure below:

The principle of exploring

  • Alloc -> _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone -> _class_createInstanceFromZone Then find initInstanceIsa into its implementation method.

    inline void objc_object::initInstanceIsa(Class cls, bool hasCxxDtor) { ASSERT(! cls->instancesRequireRawIsa()); ASSERT(hasCxxDtor == cls->hasCxxDtor()); initIsa(cls, true, hasCxxDtor); }Copy the code
  • Enter the initIsa function, which primarily initializes the ISA pointer

2. isaAssociative class exploration

The principle of CLS and ISA association class is that shiftCLs in ISA pointer stores the class information, which can be verified in the following ways

  • Method 1: PassinitIsaIn the methodnewisa.shiftcls = (uintptr_t)cls >> 3 validation
  • (2) :isa&ISA_MASK
  • (3) :isaAn operation

Method 1: Use the initIsa method

Set breakpoints and debug programs. As shown below:

The CLS attribute is null. The bits structure is initialized. By default, both values are 0

Turn on pointer optimization for ISA, from 47 to 53 bits, magic=59, indicating that the current object is initialized. The binary of 59 is 0011, 1011

Go ahead and move the address of the class three bits to the right, assigning it to Shiftcls, as shown below.

Mode 2: isa&ISA_MASK

ISA_MASK is a macro definition

  • The __arm64__ : ISA_MASK macro defines a value of 0x0000000ffffffff8ULL

  • __x86_64__ : the ISA_MASK macro defines a value of 0x00007ffffffffff8ULL

    Po 0x011D80010000820d&0x0000000FFffFF8ull (__arm64__) and Po 0x011D80010000820d& are printed in the figure 0x00007ffffffffff8ULL(__x86_64__) results in LGPerson. The ISA has been associated with a class

Mode 3: ISA bit operation

  • Class information is stored in the ISA pointer, and the shiftcls in ISA now has 44 bits (__x86_64__). To read the 44-bit information of the Shiftcls class, we need to carry over the bit operation. The bit operation is to retain only the 44-bit information of shiftcls, and erase all other bits.

  • Isa bit operation process diagram