前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >isa详解(一)isa结构

isa详解(一)isa结构

作者头像
老沙
发布2019-09-28 13:21:22
1.4K0
发布2019-09-28 13:21:22
举报
文章被收录于专栏:老沙课堂

从iOS 源码中我们可以找到以下结构体 。从这里我们开始看一下isa的构成

代码语言:javascript
复制
struct objc_object {
private:
    isa_t isa;
};
复制代码
代码语言:javascript
复制
union isa_t {
    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD) // 我们看一下这个宏
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};
我们截取了arm64部分的宏定义

复制代码
代码语言:javascript
复制
# 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)
复制代码

所以在arm64环境下isa如下所示

代码语言:javascript
复制
union isa_t {
    Class cls;
    uintptr_t bits;
  struct {
     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
  }
};
复制代码

所以为了探究isa 我们先研究下union

1. union

为什么要用union以及位运算呢。因为在计算机中为二进制。位运算是最快速的计算方式 union C++ 中的共用体。顾名思义 就是在union 中 公用一个内存地址 。

结构体 位域 : 1 只占一位

代码语言:javascript
复制
struct {
char a : 1; //1位
char b : 1; //1位
char c : 1; //1位
} temp; //3位 1个字节

struct {
char a; //1个字节
char b; //1个字节
char c; //1个字节
} temp; // 3个字节

union {
  char bits; // 一个字节
  // struct 只是可读性,有和没有都一样
  struct {
    char a : 1; //1位
    char b : 1; //1位
    char c : 1; //1位
  } temp;
} unionInstance

复制代码

union的内存结构如下图所示,两个指针指针同时管理一个内存地址。因为我们不操作struct中的 所以struct只是增强可读性。表示每个字节代表的含义。

2. 如果我们想访问union 中a,b,c的值如何设置 如何访问呢
代码语言:javascript
复制
#import "Person.h"
#define aMask (1<<0)
#define bMask (1<<1)
#define cMask (1<<2)
@interface Person()
{
    union {
        char bits;
        struct {
            int a : 1;
            int b : 1;
            int c : 1;
        } temp;
    } _property;
}
@end
@implementation Person

- (instancetype)init
{
    self = [super init];
    if (self) {
        self->_property.bits = 0b00000000;
    }
    return self;
}

- (void)setAvar:(BOOL) a {
    if (a == YES) {
        self->_property.bits |= aMask;
    }else {
        self->_property.bits =  (self->_property.bits & ~aMask);
    }
    
}
- (BOOL)a {
    return !!(self->_property.bits & aMask);
}

- (void)setBvar:(BOOL) b {
    if (b == YES) {
        self->_property.bits |= bMask;
    }else {
        self->_property.bits =  (self->_property.bits & ~bMask);
    }
    
}
- (BOOL)b {
    return !!(self->_property.bits & bMask);
}

- (void)setCvar:(BOOL) c {
    if (c == YES) {
        self->_property.bits |= cMask;
    }else {
        self->_property.bits =  (self->_property.bits & ~cMask);
    }
    
}
- (BOOL)c {
    return !!(self->_property.bits & cMask);
}
@end
复制代码
代码语言:javascript
复制
    Person *person = [Person new];
    [person setAvar:NO];
    [person setBvar:YES];
    [person setCvar:NO];
    NSLog(@"a = %d, b = %d, c = %d",person.a,person.b,person.c);
复制代码

输出结果为

代码语言:javascript
复制
    runtime-isa详解01[8059:19727104] a = 0, b = 1, c = 0
复制代码

isa指向

代码语言:javascript
复制
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
}
复制代码

我们知道isa是指向class 或者是meta-class

但是源码上为什么要 & ISA_MASK 呢。

从上面的有关union以及位运算 我们可知道 通过 &运算符 可以找到对应的union中所指向位数包含的信息

代码语言:javascript
复制
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL

union isa_t {
    Class cls;
    uintptr_t bits;
  struct {
     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
  }
};
复制代码

从上面代码我们可以知道 ISA_MASK的值为0x0000000ffffffff8ULL 所对应的取值就是isa bits 中的shiftcls所在的字节 所以 这里面才是指向class 或者meta-class的地址

  • 所以我们有一下结论

arm64之前直接指向class 或者是meta-class arm64之后 isa & ISA_MASK 为class 或者meta-class 地址。isa为 union 结构,用位域来存储更多信息 union 共用体 公用一个内存

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老沙说点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. union
  • 2. 如果我们想访问union 中a,b,c的值如何设置 如何访问呢
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档