iOS源码阅读必备知识之Tagged Pointer

所属分类: 软件编程 / IOS 阅读数: 1960
收藏 0 赞 0 分享

Tagged Pointer 介绍

苹果对于Tagged Pointer特点的介绍:

  • Tagged Pointer专门用来存储小的对象,例如NSNumber和NSDate
  • Tagged Pointer指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中,也不需要malloc和free。
  • 在内存读取上有着3倍的效率,创建时比以前快106倍。

为什么要引入Tagged Pointer

iPhone5s 采用64位处理器。对于64位程序,我们的数据类型的长度是跟CPU的长度有关的。

这样就导致了 一些对象占用的内存会翻倍。

同时 维护程序中的对象需要 分配内存,维护引用计数,管理生命周期,使用对象给程序的运行增加了负担。

Tagged Pointer

为了改进上面提到的内存占用和效率问题,苹果提出了Tagged Pointer对象。由于NSNumber、NSDate一类的变量本身的值需要占用的内存大小常常不需要8个字节,拿整数来说,4个字节所能表示的有符号整数就可以达到20多亿(注:2^31=2147483648,另外1位作为符号位),对于绝大多数情况都是可以处理的。

我们可以将一个对象的指针拆成两部分,一部分直接保存数据,另一部分作为特殊标记,表示这是一个特别的指针,不指向任何一个地址。所以,引入了Tagged Pointer对象之后,64位CPU下NSNumber的内存图变成了以下这样:

Tagged Pointer

测试

#import 

int main(int argc, const char * argv[]) {
 @autoreleasepool {
 // insert code here...
 NSNumber *number1 = @1;
 NSNumber *number2 = @2;
 NSNumber *number3 = @3;
 NSNumber *numberFFFF = @(0xFFFF);

 NSNumber *numberLager = @(MAXFLOAT);

 NSLog(@"number1 pointer is %p", number1);
 NSLog(@"number2 pointer is %p", number2);
 NSLog(@"number3 pointer is %p", number3);
 NSLog(@"numberLager pointer is %p", numberLager);

 /*
 2017-03-10 12:07:50.731726 TaggedPoint[1690:50438] number1 pointer is 0x127
 2017-03-10 12:07:50.731992 TaggedPoint[1690:50438] number2 pointer is 0x227
 2017-03-10 12:07:50.732011 TaggedPoint[1690:50438] number3 pointer is 0x327
 2017-03-10 12:07:50.732043 TaggedPoint[1690:50438] numberLager pointer is 0x1002006a0
 */


 }
 return 0;
}

以 0x127 为例 去掉 tag27(假设27为标记) 0x1 就是number 的值。

0x227

0x327

都有这种规律

numberLager 存储的值为MAXFloat 显然超过了tagged pointer 可以存储的范围。

所以打印的地址是单纯的指针地址,指向存储numberLager的内存地址。

对于isa指针的影响

因为tagged pointer 不是一个真正的对象,如果使用isa指针在编译时会报错。

如图:

提示我们改为object_getClass()

object_getClass()中做了相应的处理

由于object_getClass()没有对应的实现,只能从其他地方窥探一二

objc-weak.mm

weak_read_no_lock(weak_table_t *weak_table, id *referrer_id) 
{
 objc_object **referrer = (objc_object **)referrer_id;
 objc_object *referent = *referrer;
 if (referent->isTaggedPointer()) return (id)referent;
 //...
}
inline bool 
objc_object::isTaggedPointer() 
{
#if SUPPORT_TAGGED_POINTERS
 return ((uintptr_t)this & TAG_MASK);
#else
 return false;
#endif
}

这里取对象的值做了一些判断

如果是tagged pointer , 对象的值就是指针

如果非tagged pointer , 对象的值是指针指向的内存区域中的值

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

更多精彩内容其他人还在看

iOS画出精美的图表方法示例

这篇文章主要给大家介绍了关于iOS如何画出精美的图表的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

ios 服务器端推送证书生成的方法

这篇文章主要介绍了ios 服务器端推送证书生成的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅谈iOS推送证书生成pem文件(详细生成过程)

这篇文章主要介绍了浅谈iOS推送证书生成pem文件(详细生成过程),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

iOS高仿微信文章悬浮球功能

这篇文章主要介绍了iOS高仿微信文章悬浮球功能,本文给大家介绍的非常详细,具有一定的参考解决价值,需要的朋友可以参考下
收藏 0 赞 0 分享

通过一行代码搞定UITextField的输入格式限制

这篇文章主要给大家介绍了如何通过一行代码搞定UITextField的输入格式限制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

iOS判断是否越狱设备方法示例

这篇文章主要给大家介绍了关于iOS判断是否越狱设备的相关资料,文中通过示例代码介绍的非常详细,对各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

iOS开发教程之Status Bar状态栏设置的方法汇总

iOS 的 Status Bar 状态栏是一个比较坑的地方,所以下面这篇文章主要给大家介绍了关于iOS开发教程之Status Bar状态栏设置的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS开发之导航栏各种右滑返回失效的解决方法汇总

这篇文章主要给大家总结介绍了关于iOS开发教程之导航栏各种右滑返回失效的解决方法,文中通过示例代码介绍的非常详细,对各位iOS具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

iOS实现简单的头部缩放功能

这篇文章主要介绍了iOS 简单的头部缩放效果,头部伴随模糊效果放大缩小,并在一定位置时悬停充当导航栏,本文给大家提供实现思路,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS中震动反馈(UIFeedbackGenerator)与系统震动详解

最近要做一个项目,需要持续响铃并振动,所以就有了这篇文章,下面这篇文章主要给大家介绍了关于iOS中震动反馈(UIFeedbackGenerator)与系统震动的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多