Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V8 #44

Open
jinzhepro opened this issue Apr 23, 2023 · 0 comments
Open

V8 #44

jinzhepro opened this issue Apr 23, 2023 · 0 comments

Comments

@jinzhepro
Copy link
Owner

jinzhepro commented Apr 23, 2023

V8是一个虚拟机,作为js的执行环境,它可以模拟cpu,堆栈,寄存器等

  • 指令集(机器语言): cpu只能识别的二进制指令如(1000100111011000)
  • 汇编指令集: 人类可识别记忆的符号(mov ax,bx)

高级语言的处理

  • 解释执行(启动快,执行慢):源代码通过解析器编译成字节码,然后使用解释器解释执行字节码直接输出结果。

330ad69589d898f6609dfc083bfbe95e-1024x221

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

1f933e42e81dacc8f4f2d86e01a914d3-1024x296

V8的处理

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

8a34ae8c1a7a0f87e19b1384a025e354

字节码

V8早期并没有使用字节码,而是将JavaScript代码直接编译成机器码。为了提升性能,运行时将二进制存在内存中,并在浏览器退出时,缓存编译好的二进制到硬盘里。但是二进制实在是太大了,这种空间换时间的方法逐渐不可行,所以引入了字节码。

  • 缓存字节码要比二进制小很多,节省空间。
  • 适配CPU,统一处理

惰性解析

基于性能原因(速度慢,消耗内存),V8并不会一次性将所有的JavaScript代码全部解析为字节码。

所有主流的 JavaScript 虚拟机都实现了惰性解析。所谓惰性解析,是指解析器在执行过程中,如遇到函数声明,那么会跳过函数内部代码,而仅仅生成顶层代码的AST和字节码。

特殊情况:闭包

虽然采取了惰性解析,不会解析和执行父级函数中的子级函数,但是 V8 还是需要判断子级函数是否引用了 foo 函数中的变量,因为在正常流程中父级函数执行完毕就要销毁,这是矛盾的。负责处理这一部分的模块叫预解析器。

预解析器

预解析器的作用一个是检查函数语法错误,另一个就是检查函数内部是否引用外部变量,如果引用了,预解析器会将栈中的变量移至堆中,使用时直接使用堆中的引用。

隐藏类

#45

V8为每个对象创建了一个隐藏类,该隐藏类保存了属性的偏移值,拿到偏移值究竟可以直接去内存中获取值。但是如果在这基础上添加或删除属性,V8会重建隐藏类。

async/await

async/await就是 Promise 和生成器应用,往底层说,就是微任务和协程应用。

协程

一个比线程颗粒度更小的任务进程,他跑在线程上,一个线程可以有多个协程,但是最多只可可以同时跑一个协程。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant