背景
在现有的javascript引擎中,V8引擎绝对是其中的佼佼者,chrome和node底层都使用了V8引擎,其中chrome的市场占有率已经达到70%,而node更是前端工程化以及扩展边界的核心支柱,V8引擎对于一个前端开发工程师来说重要程度可想而知。我们大部分javascript开发者也许没有机会自己开发一个javascript引擎,但是学习V8引擎绝对是我们提升技术能力的重要途径,故专门查阅各种书籍和文章进行学习,整理出系列文章让我们一起学习进步。(本文为系列文章第一篇)
什么是V8引擎
javascript引擎
了解V8引擎之前我们先要知道什么是javascript引擎。简单来说,CPU并不认识我们的js代码,而不同的CPU只认识自己对应的指令集,javascript引擎将js代码编译成CPU认识的指令集,当然除了编译之外还要负责执行以及内存的管理。
大家都知道js是解释形语言,由引擎直接读取源码,一边编译一边执行,这样效率相对较低,而编译形语言(如c++)是把源码直接编译成可直接执行的代码执行效率更高。
(图片转载自https://zhuanlan.zhihu.com/p/...)
v8引擎
随着技术的发展,对JavaScript性能的要求越来越高,这就更快速的解析和执行JavaScript代码,V8引擎就是在此背景下产生的,它产生的目的就是为了提高性能。
为了提高性能v8向很多同时解释形语言的老前辈学习了很多经验,我们先来看一下同是解释形语言的java的运行过程。
参考文章:
什么是JIT:https://blog.csdn.net/qq_3604...
我们再看一下V8是怎么做的
整个过程和java的编译执行过程非常像,将javascript代码编译成抽象语法树再转化成字节码,通过解释器来执行,并通过JIT工具将部分字节码转化成可直接执行的本地代码。而java是分两个阶段完成,在编译阶段尽可能的生成高效的字节码。V8更加直接的将抽象语法树通过JIT技术转换成本地代码,放弃了在字节码阶段可以进行的一些性能优化,但保证了执行速度。虽然少了生成字节码这一阶段的性能优化,但极大减少了转换时间。
V8编译运行过程
接下来我们来了解一下v8的编译过程和运行过程
编译过程
首先我们要了解一下在执行编译运行过程中所用到的几个类
- Script类:表示是JavaScript代码,既包含源代码,又包含编译之后生成的本地代码,所以它既是编译入口,又是运行入口;
- Compiler类:编译器类,辅助Script类来编译生成代码,它主要起一个协调者的作用,会调用解释器(Parser)来生成抽象语法树和全代码生成器,来为抽象语法树生成本地代码;
- Parser类:将源代码解释并构建成抽象语法树,使用AstNode类来创建它们,并使用Zone类来分配内存;
- AstNode类:抽象语法树节点类,是其他所有节点的基类,它包含非常多的子类,后面会针对不同的子类生成不同的本地代码;
- AstVisitor类:抽象语法树的访问者类,主要用来遍历抽象语法树;
- FullCodeGenerator:AstVisitor类的子类,通过遍历抽象语法树来为JavaScrit生成本地代码;
原始图片来源:《WebKit技术内幕》
(红色标注为笔者自己理解,如果有偏差或者错误,欢迎指出和讨论)
运行过程
- Script表示JavaScript代码,即包含源代码,又包含编译之后生成的本地代码,即是编译入口,又是运行入口;
- Execution:运行代码的辅组类,包含一些重要函数,如Call函数,它辅组进入和执行Script代码;
- JSFunction:需要执行的JavaScript函数表示类;
- Runtime:运行这些本地代码的辅组类,主要提供运行时所需的辅组函数,如:属性访问、类型转换、编译、算术、位操作、比较、正则表达式等;
- Heap:运行本地代码需要使用的内存堆类;
- MarkCompactCollector:垃圾回收机制的主要实现类,用来标记、清除和整理等基本的垃圾回收过程;
- SweeperThread:负责垃圾回收的线程。
执行过程如下:
原始图片来源:《WebKit技术内幕》
(红色标注为笔者自己理解,如果有偏差或者错误,欢迎指出和讨论)
编译和执行的整体过程如下:
原始图片来源:《WebKit技术内幕》
(红色标注为笔者自己理解,如果有偏差或者错误,欢迎指出和讨论)
总结
本文以一个宏观的角度描述了V8引擎编辑和运行的过程,但是要想真正的了解V8除了这些,我们还需要了解很多里面的运行细节包括不限于 事件循环系统、内存管理、延迟解析、隐藏类、内联缓存等等,接下来的文章会逐一学习,敬请期待。
参考文章
《WebKit技术内幕》
认识 V8 引擎: https://zhuanlan.zhihu.com/p/...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。