1. Consortium and bitfield
1.1 structure
Let’s start with the following code:
struct SSLCar { BOOL front; BOOL back; BOOL left; BOOL right; }sslCar; NSLog (@ "sslCar: % lu", sizeof (sslCar)); SslCar: 4Copy the code
We see that an SSLCar structure is four bytes, that is, 32 bits (0000 0000 0000 0000 0000 0000 0000), whereas the four BOOL values in SSLCar require only four bits (1111) to be stored, resulting in a very large waste of space.
1.2 a domain
Specify 1 bit for each member variable by bitfield:
struct SSLCar2 { BOOL front: 1; BOOL back : 1; BOOL left : 1; BOOL right: 1; }sslCar2; NSLog (@ "sslCar2: % lu", sizeof (sslCar2)); Print result: SSLCAR2:1Copy the code
At this point, the memory space has been well optimized.
1.3 a consortium
Create a consortium:
union SSLPerson {
char *name;
int age;
};
Copy the code
Assign the union and print:
By printing the result, we find that the union only has a value for the variable that was assigned after.
1.4 Difference between structure and union
All variables in a struct are “co-existing” — the advantage is “tolerant” and comprehensive; The disadvantage is that the allocation of struct memory space is extensive, regardless of use, full allocation.
In a union, the variables are mutually exclusive — the disadvantage is that they are not “inclusive” enough. But the advantage is that memory usage is more delicate and flexible, and also saves memory space.
2. Object nature
Add the following code to main.m:
@interface SSLPerson : NSObject
@property (nonatomic, copy) NSString *sslName;
@end
@implementation SSLPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
}
return 0;
}
Copy the code
Compile main.m with the clang command (more clang info here) :
clang -rewrite-objc main.m -o main.cpp
Copy the code
We get the main. CPP file, and in main. CPP we can see information about the object:
typedef struct objc_class *Class; Struct objc_object {// 7661 line Class _Nonnull ISA __attribute__((deprecated)); }; typedef struct objc_object *id; // 7666 line typedef struct objc_object SSLPerson; // 111793 line struct SSLPerson_IMPL {// 111793 line struct NSObject_IMPL NSObject_IVARS; NSString *_sslName; };Copy the code
The object isa structure of type objc_object with an isa pointer of type Class.
Open the source code and check out objc_object:
struct objc_object { private: isa_t isa; . }Copy the code
3. Isa structure analysis
We in the OC object principle exploration (a), mentioned obj->initIsa(CLS), its role is to associate Pointers and classes, we use the source code for detailed analysis.
InitIsa function:
inline void objc_object::initIsa(Class cls) { initIsa(cls, false, false); } objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) { ASSERT(! isTaggedPointer()); isa_t newisa(0); // isa initializes if (! nonpointer) { newisa.setClass(cls, this); } else {ASSERT(! DisableNonpointerIsa); ASSERT(! cls->instancesRequireRawIsa()); #if SUPPORT_INDEXED_ISA ASSERT(cls->classArrayIndex() > 0); newisa.bits = ISA_INDEX_MAGIC_VALUE; newisa.has_cxx_dtor = hasCxxDtor; newisa.indexcls = (uintptr_t)cls->classArrayIndex(); #else newisa.bits = ISA_MAGIC_VALUE; # if ISA_HAS_CXX_DTOR_BIT newisa.has_cxx_dtor = hasCxxDtor; # endif newisa.setClass(cls, this); #endif newisa.extra_rc = 1; } isa = newisa; }Copy the code
Click to see isa_t;
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
};
Copy the code
Click to see 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__
# 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)
Copy the code
Take a look at isa’s memory distribution:
nonpointer
: indicates whether it is correctisa
Pointer Pointer optimization is enabled.0
: pureisa
A pointer,1
: Not only class object address,isa
Contains class information, object reference counts, and so on.has_assoc
: Flag bit of the associated object,0
No,1
There is.has_cxx_dtor
: Indicates whether the object hasC++
orObjc
If there is a destructor, it needs to do the destructor logic, if there is no, it can be faster to free the object.shiftcls
: Stores the value of the class pointer. Turn on pointer optimization in case ofarm64
In the architecture33
Bits are used to store class Pointers.magic
: used by the debugger to determine whether the current object is a real object or has no space to initialize.weakly_referenced
: indicates whether the object is or has been pointed to oneARC
Objects without weak references can be freed faster.deallocating
: indicates whether the object is freeing memory.extra_rc
: represents the reference count value of the object. If there is not enough storage,has_sidetable_rc
The value of delta is going to be 1;has_sidetable_rc
: if for1
, indicating that the reference count is too large to be stored inisa
In, the excess reference count is stored inSideTable
theRefCountMap
In the. So, ifisa
isnonpointer
, the object’s reference count is stored in itsisa_t
theextra_rc
And in theSideTable
theRefCountMap
In the.
Conclusion:
isa
Divided intononpointer
The types and thenonpointer
Type. nonnonpointer
The type is a pure pointer,nonpointer
A type also contains information about reference counts, associated objects, and so on.isa
usingA consortium
+A domain
To store information. Because in theiOS
Everything is object, object is used inisa
, which can greatly save memory space.
4. Isa association class
Create an SSLperson class, initialize [SSLperson alloc], and debug in initIsa:
As shown in the figure above, a union newisa is created where the variables are currently 0 and no values are assigned.
Continue down:
As shown in the figure above, newISa.bits = ISA_MAGIC_VALUE, ISA_MAGIC_VALUE isa macro = 0x001D800000000001. The variables assigned are bits=8303511812964353, CLS = 0x001D800000000001, NonPointer =1, magic=59. Convert to binary representation:
0x001d800000000001
=8303511812964353
, their binary representation is the same.nonpointer
The binary representation of1
.magic
The binary representation of111011
, they are contained inbits
Binary representation of.
Breakpoint to enter setClass:
- here
isa
andSSLPerson
Class is associated. - Is currently the
nonpointer
“, so it will not be givencls
The assignment. SSLPerson
A class of address> > 3
for10
Base conversion, and then assign toshiftcls
.- Why move to the right
three
?shiftcls
inisa
Is stored from the fourth bit, like thisisa & ISA_MASK
In order to get accurateClass address
.
- Why move to the right
Continue down:
shiftcls
.extra_rc
Is also successfully assigned.- I’ve always had a question here
cls
Why is it assigned when it’s notSSLPerson
, andA consortium
I should be able tocls
So I did a debugging in the later stage:- Print the
cls
Phi, it’s really the wholeisa
The value of, as for why displaySSLPerson
I think the system did something.
- Print the
At this point, the exploration of isa and class association is basically completed, and will continue to be updated if there isa deeper understanding in the future.