V8的浏览器运行时环境

V8是如何提升对象访问速度

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

高级语言

V8

融合解释执行和编译执行(Just In Time)

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/12f7b4fc-521c-4d32-9c23-c438eb294225/8a34ae8c1a7a0f87e19b1384a025e354.jpg

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

字节码

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

引入字节码有几个好处:

惰性解析

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

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

特殊情况:闭包

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

预解析器

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

隐藏类

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/03643686-6104-47dc-98e2-c7a6ef666628/51f5034a7f80e4e5684d5a301178c2f8.jpg

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