Runtime笔记(一)—— isa的深入体会(苹果对isa的优化)


Runtime系列文章

Runtime笔记(一)—— isa的深入体会(苹果对isa的优化)
Runtime笔记(二)—— Class结构的深入分析
Runtime笔记(三)—— OC Class的方法缓存cache_t
Runtime笔记(四)—— 刨根问底消息机制
Runtime笔记(五)—— super的本质
[Runtime笔记(六)—— Runtime的应用…待续]-()
[Runtime笔记(七)—— Runtime的API…待续]-()
Runtime笔记(八)—— 记一道变态的runtime面试题

☕️☕️本文篇幅比较长,创作的目的并不是为了在简书上刷赞和阅读量,而是为了自己日后温习知识所用。如果有幸被你发现这篇文章,并且引起了你的阅读兴趣,请休息充分,静下心来,精力充足地开始阅读,希望这篇文章能对你有所帮助。如发现任何有误之处,肯请留言纠正,谢谢。☕️☕️

如何理解Objective-C的动态特性?

很多静态编程语言,编写完代码后,经过编译连接生成可执行文件,最后就可以在电脑上运行起来。

以C语言为例

void test() {
   
    printf("Hello World");
}
int main() {
   
    test();
}

以上代码经过编译之后,main函数里面就一定会调用test(),而test()的实现也一定会是和代码中写的一样,这些在编译完成那一刻就决定了,运行过程中不会发生改变的。C可以说就是典型的静态语言。

与之相比,Objective-C就可以在运行阶段修改之前编译阶段确定好的一些函数和方法。

************************main.m*************************
#import <Foundation/Foundation.h>
#import "CLPerson.h"

int main(int argc, const char * argv[]) {
   
    @autoreleasepool {
   
        CLPerson *person = [[CLPerson alloc] init];
        [person test];
    }
    return 0;
}

***********************CLPerson.h************************
#import <Foundation/Foundation.h>
@interface CLPerson : NSObject
- (void)test;
@end


***********************CLPerson.m************************
#import "CLPerson.h"
@implementation CLPerson
- (void)test {
   
    NSLog(@"%s", __func__);
}

- (void)abc {
   
    
}
@end

如上面所示代码,[person test];这句代码,在运行阶段,可以调用CLPersontest方法,也可以通过OC的动态特性,使其最终调用别的方法,例如abc方法,甚至,还可以调用另外一个类的方法。除此之外,OC还可以在程序运行阶段,给类增加方法等,这就是所谓的动态特性


Runtime简介

  • Objective-C是一门动态性比较强的编程语言,根 C、C++ 等语言有很大不同
  • Objective-C的动态性是由Runtime API来支撑的
  • Runtime API提供的接口基本都是C语言的,源码由C/C++/ 汇编语言编写

isa详解

深入Runtime之前,先要解决一个比较重要的概念——isa。在早期的Runtime里面,isa指针直接指向class/meta-class对象的地址,isa就是一个普通的指针。

后来,苹果从ARM64位架构开始,对isa进行了优化,将其定义成一个共用体(union)结构,结合 位域 的概念以及 位运算 的方式来存储更多类相关信息。isa指针需要通过与一个叫ISA_MASK的值(掩码)进行二进制&运算,才能得到真实的class/meta-class对象的地址。接下来,就具体探究一下苹果究竟是怎么优化的。

首先从源码角度,对比一下变化isa优化前后的变化

***************************************
typedef struct objc_class *Class;

typedef struct objc_object {
   
	Class isa;
} *id;

上面是64位之前,objc_object的定义如上,isa直接指向objc_class

再看看优化后objc_object的定义

struct objc_object {
   
private:
    isa_t isa;

public:

arm64开始,isa的类型变成了isa_t,这是什么鬼?这个就是接下来讨论的重点,先看一下它的源码

union isa_t 
{
   
    isa_t() {
    }
    isa_t(uintptr_t value) : bits(value) {
    }

    Class cls;
    uintptr_t bits;

#if SUPPORT_PACKED_ISA

   

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
    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;
#       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
    struct {
   
        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

#   define ISA_INDEX_IS_NPI      1
#   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
    struct {
   
        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优化的精华所在,为了看懂上面的代码,首先需要从一些基础知识开始说。

场景需求分析

首先定义一个类CLPerson,首先给CLPerson增加几个属性以及成员变量

@interface CLPerson : NSObject
{
   
    BOOL _tall;
    BOOL _rich;
    BOOL _handsome;
}
@property (nonatomic, assign, getter=isRich) BOOL rich;
@property (nonatomic, assign, getter=isTall) BOOL tall;
@property (nonatomic
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值