Google V8 引擎工做原理(翻译)

V8 引擎如何执行JS,以前看过 Webkit 技术内幕,也只是蜻蜓点水。并无深刻理解,忽然看到这篇文章,翻译之How does the Google V8 engine work?html

Google V8 引擎是如何工做的?这是一个很是好的问题,这里有少量流出的官方文档来说解,到底 V8 内部都作了什么。我会把我知道的东西分享给你(你须要本身猜,哪部分我给拿掉了),还有不少有用的地址去帮助你明白这些内容。git

V8 有两个编译器:github

  • 一个很是简单而且很是快的编译器用于将 js 编译成简单可是很慢的机械码,叫作 full-codegen
  • 另外一个是很是复杂的实时优化编译器,编译高性能的可执行代码,叫作 Crankshaft

V8 里面也使用了一些线程:缓存

  • 主线程,作你但愿它作的事情:加载你的代码,编译它们,执行他们。
  • 有一个独立的编译线程,当主线程执行的时候,它去优化代码。
  • 一个 profiler 线程(不知道还有没有了,可是会有一个一样职责的线程存在),用于发现执行过程当中哪一个方法耗费了大量时间,这样 Crankshaft 就能够优化这些代码。
  • 一些用于 GC 处理的线程(译者注:这里是一些用于 GC 的线程,不止一个线程用于垃圾回收)。

最开始执行你的代码的时候,V8 开始使用 full-codegenfull-codegen 直接将 JS 代码解释成机械码,没有作任何转化。这可让 V8 快速执行机械码。注意,V8 并不使用中间字节码,所以也就再也不须要转译处理。架构

当你的代码被执行的时候,profiler 线程有足够的数据来找出哪些方法须要被优化。我不肯定 V8 如何选择使用哪一个线程作的优化,简单起见,咱们就认为它用的主线程吧。ide

主线程经过中止正在执行的代码(也许就在须要优化的方法这里),开始使用 Crankshaft 进行优化。JS 代码首先会被编译成一种叫作 Hydrogen 的高级描述,它是控制流图的静态单赋值表示。大多数优化都是在这个级别完成的。oop

首先,对尽量多的代码进行内联,这使得优化变得更有意义。而后进行类型转化。这个优化移除了打包和拆包的处理,能够认为是执行了不少指令。这意味着,若是你的代码在操做整数,而且没有作类型转换,好比转换成 stringdouble 这些,那么它会跑的很快。内联缓存会在这个阶段起到很是重要的做用,提供了类型判断。就像你猜到的那样,咱们须要当心类型转换:若是你但愿一个变量是一个整数,可是过一会却被修改为了其它类型,那么你的假设就失败了,那么一次从新编译就在所不免了。还有其它的优化,好比 loop-invariant code motion(译者注:貌似是讲将循环内不变化的代码移到外面,减小每一次循环执行的代码数量),移除死代码(译者注:不被执行的代码也要移除,不然 V8 始终都要要对这些代码处理的,带来了额外负担)等。post

一旦 Hydrogen graph 被优化,Crankshaft 会下降它到一个低级别的描述,叫作 Lithium。大部分的 Lithium 执行于特定架构。分配寄存器就是在这个级别进行的。性能

最终,Lithium 被编译成机械码。而后一些叫作 OSR (on-stack replacement)的事情就发生了。记住,在咱们开始编译和优化运行耗时较长的方法以前,咱们喜欢先执行它。咱们不要忘记咱们刚刚放慢了执行,而后开始执行优化后的代码。相反,咱们将要转换全部的上下文,所以咱们才能在执行的中间过程当中选择执行优化后的代码。我让大家感到复杂,提醒一下,其它的优化中,咱们内联了一些东西。V8 并非惟一一个这么作的虚拟机,可是我发现一些比较疯狂的地方。有一些保护机制叫 -- 去优化,在作相反的事情,而且会在一些假设的特定状况下反转一些优化后的代码。优化

还有。就是编译/执行部分。我忘了提到 GC,不过这很短,由于我对它不太了解。

对于垃圾收集来讲,V8 使用了传统的方法,采用标记计数的方式来进行垃圾收集。标记阶段必须中止 JavaScript 执行。为了控制 GC 成本,使执行更加稳定,V8 采用增量标记。这就是说,他们不是在堆中试图标记每个可能的对象,而是处理一部分堆,而后恢复正常的执行。下一个 GC 中止执行代码的时候处理以前未处理的堆。这容许很是短的暂停。如前所述,扫描阶段由单独的线程来处理。

posts tagged "v8"

Posts Tagged 'v8'

V8 Resources

thlorenz/v8-perf

docs.google.com/document...

floitsch.blogspot.de/2012/04/opt…

还有这里源码

相关文章
相关标签/搜索