V8引擎簡介——如何編譯和執行JS代碼


1.用處

  • chrome瀏覽器的引擎
  • Nodejs的運行時環境
  • electron的底層引擎

2.什么是V8引擎

  •  是用C++編寫的Google開源高性能JS和WebAssembly引擎
  • 簡而言之:是一個接收JS代碼,編譯代碼然后執行的C++程序,編譯后的代碼可以在多種操作系統,多種處理器上運行

主要的工作:

  1. 編譯和執行JS代碼
  2. 處理調用棧
  3. 內存的分配
  4. 垃圾的回收

3.溯源

大部分JS引擎在編譯和執行JS代碼都會用到三個重要的組件:

  • 解析器
    • 負責將JS源代碼解析成抽象語法樹AST
  • 解釋器
    • 負責將AST解釋成字節碼bytecode
    • 也有直接解釋執行bytecode的能力
  • 編譯器
    • 負責編譯出運行更加高效的機器代碼

早期的V8引擎是如何編譯和執行JS代碼的:

  在V8早期5.9版本之前,V8引擎沒有解釋器,卻有兩個編譯器:

  • JS由解析器解析后,生成AST抽象語法樹
  • 然后由編譯器(Full-codegen)直接使用AST來編譯出機器代碼,而不進行任何中間轉換
    • Full-codegen又稱基准編譯器,因為它生成的是一個基准的未被優化的機器代碼
  • 還有另一個編譯器(Crankshaft)——優化編譯器:用來優化代碼,提升性能

缺陷:

  • 生成的機器碼會占用大量的內存
  • 缺少中間的字節碼,很多性能優化策略無法實施——V8性能提升緩慢
  • 無法很好的支持和優化JS的新語法特性

4.目前的V8引擎

  • 網頁初始化解析執行JS的時間縮短了,網頁能夠更快的onload
  • 在生成的優化機器代碼時,不需要從源碼重新編譯,而使用字節碼,並且當需要回退字節碼時,只需要回歸到中間層的字節碼解釋執行就可以了

5.V8引擎中處理JS過程中的一些優化策略

  1. 如果函數只是聲明而未被調用,則不會被解析生成AST
  2. 函數如果只被調用一次,bytecode直接被解釋執行
  3. 函數被調用多次,可能會被標記為熱點函數,可能會被編譯成機器代碼——提高代碼的執行性能。
    1. 之后執行這個函數時,就直接運行優化后的機器代碼 
    2. 隨着JS代碼的不斷執行,會有更多的代碼被標記為熱點代碼,也就會產生更多的機器代碼
    3. 此時會有一個問題:回退字節碼。
      1. 造成的原因是:如一個sum函數,參數是a,b,多次調用傳入整數,且被識別為熱點函數,解釋器將收集到參數和函數信息編譯成優化后的機器碼,這里就會假定了sum函數的參數就是整形的
      2. 但是如果某次你傳入的不是整數,而是字符串,機器不知道如何處理字符串類型的參數,此時就會deoptimization(回退字節碼)
      3. 總結:不要把一個變量類型變來變去,傳入的參數的類型也要固定一下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM