当前位置: 首页 > news >正文

【JavaScript运行原理之V8引擎】V8引擎解析JavaScript代码原理

1. 编程语言的执行

高级语言最终都需要编译为低级语言才能被硬件执行,越高级的语言中间的转换时间越长,效率越低,越低级的语言执行素的越快,但是由于缺少高级语言便捷的语法特性所以很难编写代码。

2. 大杂烩JS

它是作者在1995年花10天写出来的,整个语言差不多是很多语言的大杂烩:

  • 借鉴了C语言的基本语法;
  • 借鉴了Java的数据类型和内存管理
  • 借鉴了Scheme语言,将函数作为一等公民
  • 借鉴了Self语言,使用了原型继承机制,基于原型prototype的继承机制
    所以JS算是 函数式编程 和 面向对象编程的混合产物。

3. 动态语言JS

通过var声明一个变量,可以给这个变量赋值任何数据类型的值,所以称js是一门动态语言。

但这也有一个缺点:我们在声明了复杂数据类型以后,可以随便删除、修改里面的属性,这对开发者来说是很爽的,但是对于编译器来说就是一场灾难,因为源代码里提供的信息太少了,js的语言特性让编译器没办法在运行前知道变量的类型,只有在运行期间才能确定各个变量的类型,这就导致了JS无法在运行前编译出更加迅速的低级语言代码。

但是现在的JS编译引擎都使用了运行时编译,在运行时阶段生成机器代码,而不是提前生成,这就是把代码的运行和生成机器代码同时执行,在运行阶段收集变量的类型信息,然后根据这些信息编译生成机器代码,然后直接使用这些机器代码。像Java这样的语言都是在运行前生成好机器代码。

4. JavaScript引擎

JS作为一门高级语言,它被CPU执行之前,需要通过某种程序将js转换成机器语言并执行,这种程序就是JavaScript引擎。
JavaScript有很多引擎但是在编译JS时流程是差不多的:

  1. 将js源码通过解析器解析成抽象语法树AST;
  2. 接着通过接着再通过解释器将AST编译成字节码,字节码与平台无关,可以在任何操作系统上运行
  3. 字节码最后通过编译器生成机器码,由于不同平台使用 的机器代码会有差异,所以编译器会根据当前平台生成相应的机器码(汇编代码)。
    这是一个简化流程,在不同JS引擎中表现会有一定的差异。

5. 什么是V8引擎

V8 是一个接收JavaScript代码,并编译代码,执行代码的一个C++程序,编译后的代码可以在多种操作系统,多种处理器上运行。

V8的工作:编译执行js代码、处理调用栈、内存分配、垃圾回收。

6. V8如何编译执行js代码

一般引擎在编译执行js代码都会用到3个重要的组件:解析器、解释器、编译器。

  • 解析器:负责将js源代码解析为抽象语法树AST
  • 解释器:将AST解释为字节码,同时解释器也有直接解释执行字节码的能力
  • 编译器:将字节码编译为运行高效的汇编语言(机器码)

编译流程:

  1. 由解析器将js解析为抽象语法树AST
  2. 通过解释器将AST生成字节码,此时AST就被清除了,释放内存空间。生成的字节码直接被解释器执行,同时生成的字节码将作为基准执行模型,
  3. 在代码不断运行的过程中,解释器会收到很多可以用于优化代码的信息,比如变量的类型,哪些函数执行的频率较高这些信息会收集给编译器,编译器会根据这些信息编译出经过优化的机器代码

注意: 优化后的机器代码也可能会被还原成字节码,因为js时一门动态语言,会导致编译器收集到的变量的类型不一致,比如你一开始声明函数接收的参数时int类型,函数被标记为热点函数后就会生成机器码,但是后边调用函数你传入的参数时String类型,机器码不知道如何处理字符串参数,于是就需要回退到字节码,由解释器来解释执行,效率就会变低。所以我们尽量不要把一个变量的类型变来变去(TS了解一下)。

7. 编译器处理js过程中的优化策略:

  1. 若函数只是声明,没有被调用,则不被解析生成AST
  2. 若函数只被调用一次,则生成字节码后就直接被解释执行,不会进行优化编译为机器代码
  3. 函数若被调用多次,则可能会被标记为热点函数,可能会被编译为机器代码,之后调用这个函数时,直接调用机器代码
http://www.lryc.cn/news/36943.html

相关文章:

  • C++11:智能指针
  • ccc-pytorch-RNN(7)
  • docker安装(linux)
  • 【数据库概论】10.1 事务及其作用
  • 通讯录(C++实现)
  • 轻松掌握C++的模板与类模板,将Tamplate广泛运用于我们的编程生活
  • pandas 数据预处理+数据概览 处理技巧整理(持续更新版)
  • mmdetectionV2.x版本 训练自己的VOC数据集
  • Shell - crontab 定时 git 拉取并执行 maven 打包
  • 408考研计算机之计算机组成与设计——知识点及其做题经验篇目3:指令的寻址方式
  • 前端包管理工具:npm,yarn、cnpm、npx、pnpm
  • 推荐系统 FM因式分解
  • Maven基础入门
  • 传输层协议 TCP UDP
  • 一点就分享系列(实践篇6——上篇)【迟到补发】Yolo-High_level系列算法开源项目融入V8 旨在研究和兼容使用【持续更新】
  • buu RSA 1 (Crypto 第一页)
  • Python 二分查找:bisect库的使用
  • 性能优化之HBase性能调优
  • 图像金字塔,原理、实现及应用
  • 08-Oracle游标管理(定义,打开、获取数据及关闭游标)
  • Python判断字符串是否包含特定子串的7种方法
  • aop实现接口访问频率限制
  • Hive---窗口函数
  • JavaSe第7次笔记
  • 什么是 Service 以及描述下它的生命周期。Service 有哪些启动方法,有 什么区别,怎样停用 Service?
  • Redis部署
  • AT32F437制作Bootloader然后实现Http OTA升级
  • Springboot项目启动初始化数据缓存
  • 深度学习必备知识——模型数据集Yolo与Voc格式文件相互转化
  • 数据、数据资源及数据资产管理的区别