V8
V8 是一个虚拟机,作为 js 的执行环境,它可以模拟 cpu,堆栈,寄存器等
- 指令集(机器语言): cpu 只能识别的二进制指令如(1000100111011000)
- 汇编指令集: 人类可识别记忆的符号(mov ax,bx)
高级语言的处理
- 解释执行(启动快,执行慢):源代码通过解析器编译成字节码,然后使用解释器解释执行字节码直接输出结果。

- 编译执行(启动慢,执行快):源代码通过解析器编译成字节码,然后通过编译器编译为机器代码,机器代码可以通过内存或者文件的形式保存,然后直接执行二进制。

V8 的处理
融合解释执行和编译执行(Just In Time):准备执行环境 → 解析源码生成 AST 和作用域 → 生成字节码 → 解释字节码输出结果 → 监控热点代码 → 热点代码编译为机器码执行 → 反优化生成的机器码(抛弃当前优化的二进制代码,回退使用字节码解释执行)

字节码
V8 早期并没有使用字节码,而是将 JavaScript 代码直接编译成机器码。为了提升性能,运行时将二进制存在内存中,并在浏览器退出时,缓存编译好的二进制到硬盘里。但是二进制实在是太大了,这种空间换时间的方法逐渐不可行,所以引入了字节码。
- 缓存字节码要比二进制小很多,节省空间。
- 适配 CPU,统一处理
惰性解析
基于性能原因(速度慢,消耗内存),V8 并不会一次性将所有的 JavaScript 代码全部解析为字节码。
所有主流的 JavaScript 虚拟机都实现了惰性解析。所谓惰性解析,是指解析器在执行过程中,如遇到函数声明,那么会跳过函数内部代码,而仅仅生成顶层代码的 AST 和字节码。
特殊情况:闭包
虽然采取了惰性解析,不会解析和执行父级函数中的子级函数,但是 V8 还是需要判断子级函数是否引用了 foo 函数中的变量,因为在正常流程中父级函数执行完毕就要销毁,这是矛盾的。负责处理这一部分的模块叫预解析器。
预解析器
预解析器的作用一个是检查函数语法错误,另一个就是检查函数内部是否引用外部变量,如果引用了,预解析器会将栈中的变量移至堆中,使用时直接使用堆中的引用。
隐藏类
V8 为每个对象创建了一个隐藏类,该隐藏类保存了属性的偏移值,拿到偏移值究竟可以直接去内存中获取值。但是如果在这基础上添加或删除属性,V8 会重建隐藏类。
async/await
async/await 就是 Promise 和生成器应用,往底层说,就是微任务和协程应用。
协程
一个比线程颗粒度更小的任务进程,他跑在线程上,一个线程可以有多个协程,但是最多只可可以同时跑一个协程。
本文来自博客园,作者:jinzhepro,转载请注明原文链接:https://www.cnblogs.com/jinzhepro/p/19233993

浙公网安备 33010602011771号