一、v8基础运行环境
v8执行javascript代码的时候需要一些基础环境,如:堆空间、栈空间、消息循环系统、全局上下文和全局作用域等,那么这些是由宿主提供如浏览器或node,v8自身提供核心函数和垃圾回收机制。以下是宿主与v8的关系:
- 堆空间和栈空间
栈空间:提供连续的存储空间,容量小,先进后出;因为地址是固定的,所以查询效率比较高,但不适合修改数据,这会导致数据的位移
堆空间:树形存储结构,存储离散的引用数据类型,存储空间大 - 全局上下文和全局作用域
全局上下文:- 上下文提供词法环境,变量环境,this关键字
- 存储在堆中,v8初始化后不会被销毁
- 全局上下文和其他函数上下文会形成栈结构,通过进栈出栈的形式控制函数执行位置
全局作用域: - 作用域是变量和函数所能访问的范围,作用域控制变量和函数的访问性和生命周期
- 上下文内可以有多个作用域
- 作用域又分为函数作用域、代码块作用域、文件作用域、原型作用域和全局作用域
- 消息循环系统
循环执行消息队列里面任务的机制,也是V8的核心机制
二、V8如何运行js代码
- 混合解析执行和编译执行(JIT)
- js代码通过解析器转成抽象语法书AST
- v8解析执行会将AST转换成字节码,编译执行会将AST转换成二进制机器码
- 通过解释器识别执行字节码;二进制代码则直接被CPU识别执行,执行效率高
- 解释器在执行字节码过程中将监控代码,如果代码频繁使用则标记为热点代码,并将其转换成优化后的二进制代码存储,下次运行相同代码会直接运行优化二进制代码
- 如果优化后的二进制代码结构或类型被修改,则会触发反优化操作,将优化二进制代码重新转成字节码给解释器执行
执行流程图如下所示:
三、理解v8编译流水线具备知识点
- 二进制代码如何在CPU上执行
- 堆和栈如何影响内存布局
- v8如何通过延迟解析实现闭包
- v8为什么映入字节码
- 解释器如何解释字节码
- 如何通过隐藏类实现快速查找对象属性
- v8如何通过内联缓存IC提升函数执行效率