前置:
- v8中数据主要分到两块存储,分别是堆栈
- js有7种基本数据类型和一个object类型
栈用于管理上下文,一个上下文环境包括变量环境和词法环境,变量都放置在变量环境,如果变量是基本类型,变量直接指向值,如果变量是对象,则变量指针指向对象的内存地址,对象数据被放在堆空间。
内存销毁
- 栈:通过ESP,直接切换栈帧,也就是切换上下文,快速实现内存销毁
- 堆: 堆中根据边际效应,将堆区设计为的老生代和新生代两块区域,新生代用于存储新创建的小对象,老生代用于存取访问超过一定次数或者大对象 新生代和老生代使用不同的内存销毁算法
-
新生代使用Scavenge算法 将新生代的内存区域分为两块,一块处于使用记为from,另外一块处于闲置中记为to。当开始进行垃圾回收的时候,检查from空间的存活对象,将存活对象拷贝到to对象并做内存整理,避免引入过多的碎片。原来的from空间现在变为to空间,原来的to空间变为新的from空间。当某个对象在生存在经过两次置换后还存活在新生代,则该对象会采取晋升策略上升到老生代。
-
老生代采用增量标记算法 在老生代发生内存销毁事,V8会从根节点(全局上下文)开始遍历,标记不活动对象,标记后,销毁不活动对象,并对内存进行整理,避免生成内存碎片。由于js执行是单线程的,在内存销毁时,会停止其它的js脚本以及UI线程执行(stop-the-world),为了解决这个问题,v8引入了增量标记,将整个标记过程分片。不过分片的仅仅是增量标记的过程,销毁和整理的过程还是会阻塞到js的执行。