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…

還有這裏源碼

相關文章
相關標籤/搜索