前言
什么是 V8?JAVAScript運行的背后發生了什么?
如果你是一個 JS 開發者或者是正在學習這門語言的學生,很大概率上你會遇到雙字母詞”V8”。在這篇文章中,我將會為你簡述不同的 JS 引擎并深入探究 V8 引擎的工作機制。文章的第二部分涵蓋了內存管理的概念,不久后將發布。
這篇文章是由 Bit (GitHub) 帶來的。作為一個共享組件的平臺,Bit 幫助每個人構建模塊化的 JavaScript 應用程序,在項目和團隊之間輕松地共享組件,同時實現更好&更快的構建。試試看。
1.編程語言是如何工作的?
在開始講解 JavaScript 之前,我們首先要理解任意一門編程語言的基本工作方式。電腦是由微處理器構成的,我們通過書寫代碼來命令這臺小巧但功能強大的機器。但是微處理器能理解什么語言?它們無法理解 Java,Python 等語言,而只懂機器碼。
用機器語言或匯編語言編寫企業級代碼是不可行的,因此我們需要像 Java,Python 這樣配帶一個解釋器或者編譯器用于將其轉換為機器碼的高級語言。
1.1編譯器和解釋器
編譯器/解釋器可以用它處理的語言或任何其他語言來編寫。
解釋器: 一行一行地快速讀取和翻譯文件。這就是 JavaScript 最初的工作原理。
編譯器: 編譯器提前運行并創建一個文件,其中包含了輸入文件的機器碼轉換。
有兩種途徑可以將 JavaScript 代碼轉換為機器碼。編譯代碼時,機器對代碼開始運行前將要發生的事情有更好的理解,這將加快稍后的執行速度。不過,在這個過程之前需要花費時間。
另一方面,解釋代碼時,執行是立即的,因此要更快,但是缺乏優化導致它在大型應用程序下運行緩慢。
創建 ECMAScript 引擎的人很聰明,他們集二者之長開發了 JIT(Just-in-time) 編譯器。JavaScript 同時被編譯和解釋,但實際實現和順序取決于引擎。我們將會看到 V8 團隊采用的是什么策略。
2.從 JavaScript 到機器碼
就 JavaScript 而言,有一個引擎將其轉換為機器碼。和其他語言類似,引擎可以用任何語言來開發,因此這樣的引擎不止一個。
- V8 是谷歌針對 Chorme 瀏覽器的引擎實現。
- SpiderMonkey 是第一個引擎,針對網景瀏覽器開發,現用于驅動 FireFox。
- JavaScriptCore 是蘋果針對 Safari 瀏覽器使用的引擎。
還有很多,如果你想知道 Internet Explorer 背后的引擎,查看這個維基百科頁面.
2.1 ECMAScript
面對這么多的引擎,你可能會問:我可以開發自己的引擎嗎?可以,只要遵循 ECMAScript 標準。
如果我們打算做一個翻譯器,那么就必須知道這兩門語言的有效字。我們已經知道機器語言中什么是有效的了,但是對于 JavaScript,這是需要進行標準化的。
JavaScript 的標準化工作是由 Ecma 國際組織負責的,相關規范被稱為 ECMAScript 或者 ES。因此,當你看到一篇文章/視頻提到“ES7 有什么新特性?”時,你就知道它代表的是 ECMAScript 標準中新增的 JS 特性。
3.V8 引擎
3.1 部分歷史
谷歌針對瀏覽器開發了谷歌地圖,而這對瀏覽器的處理能力提出了很高的要求。那時的 JavaScript 實現尚不足以快速地運行地圖。谷歌想要吸引更多的用戶使用這項服務,從而進行廣告銷售并牟利。基于這個原因,這項服務必須快速且穩定。因此谷歌自己用 C++ 開發了 V8 引擎并在 2008 年啟用,它的速度很快,或者就像一些人說的,它的速度是最快的。
3.2 解析和構建樹
JavaScript 文件進入引擎后,解析器進行詞法解析,它將代碼分解成 token 以確定它們的含義。這些 token 組成了AST(抽象語法樹)。
編譯器在語義分析中驗證語言元素和關鍵詞的正確用法,而 ASTs 在這個過程中扮演著重要的角色。之后,ASTs 被用于生成實際的字節碼或者機器碼。
3.3 引擎的核心
我們之前談到,JavaScript 是由 Ignition 這個解釋器解釋的,同時由 TurboFan 這個 JIT 優化編譯器進行編譯。
首先,前面步驟生成的 ASTs 傳遞給解釋器,該解釋器迅速生成未經過優化的機器碼,并且其執行是無延遲的。
Profiler 在代碼運行時進行觀察,找出可以進行優化的地方。例如,一個‘for’循環跑了 100 次,但是每次迭代產生的結果都是一樣的。
使用這個分析器后,任何未優化的代碼都將傳遞給編譯器以進行優化,同時生成機器碼,它最終會替換掉之前由解釋器生成的未優化代碼中的對應部分。
隨著分析器和編譯器不斷地更改字節碼,JavaScript 的執行性能逐漸提高。
3.4 更多歷史
在V8 的 5.9 版本推出之前,它使用兩個優化編譯器和一個基線編譯器。
- 基線編譯器 full-codegen 迅速生成未優化的機器碼。
- 兩個優化編譯器 Crankshaft 和 TurboFan 用于優化代碼。
JavaScript 增加了新的特性后,架構的復雜度上升,維護相同的管道對 V8 團隊來說變得更加困難了。如果你想閱讀更多相關的舊方法以及轉向新管道的原因,可以訪問他們的網站。
3.5 放眼未來
隨著更多進一步提升性能的研究的進行,V8 引擎的工作機制在未來還可能發生變化。此外,隨著 Webassembly 逐漸成形,可能會向管道添加額外步驟。
4.結論
ECMAScript 引擎的實現有很多,其中以谷歌的 V8 最為出名。希望這篇文章的簡述不僅可以幫助你理解 JavaScript 的工作原理,還能從大體上了解一門編程語言的工作原理。如果你想了解 V8 團隊的未來計劃或者引擎的細節,這里有一篇很不錯的博客。
關于本文
譯者:@Chorer
譯文:https://chorer.github.io//2019/05/10/Trs-Javascript 究竟是如何工作的?(第一部分)/
作者:@Priyesh Patel
原文:https://blog.bitsrc.io/how-does-javascript-really-work-part-1-7681dd54a36d