WebAssembly進階系列二:WebAssembly處於編譯階段哪一個環節

導語:相信很多人據說過 WebAssembly,它是由 Google、Microsoft、Mozilla、Apple 等幾家大公司合做發起的一個關於面向Web的通用二進制和文本格式的項目。如今就讓咱們一步步揭開WebAssembly的神祕面紗,並親自動手將WebAssembly應用在實際業務中。前端

1. 引言

衆所周知,不管是Chrome、Firefox、Safari、Edge仍是其餘瀏覽器,可以運行的語言就是Javascript。爲了可以讓其餘語言的代碼在瀏覽器中運行,WebAssembly被創造出來,詳見《WebAssembly進階系列二:WebAssembly是什麼》。咱們並不須要親自編寫WebAssembly的代碼,惟一要作的就是把其餘高級語言編譯成WebAssembly便可,這樣便能複用大量其餘語言現有的代碼。並且WebAssembly還擁有比JavaScript更好的性能,可以更快的加載和執行。git

那爲啥WebAssembly的性能就必定會比JavaScript好不少呢?具體緣由還得看下它們究竟是處於編譯階段哪一個環節了。程序員

2. 編譯步驟

做爲程序員的咱們,天天都在用各類高級語言寫源代碼。但要讓機器能讀懂這些字符串代碼,就得靠編譯系統一步步把它們編譯成目標代碼。github

(1) 預編譯web

預編譯首先會處理源代碼中那些以#開頭(如#include、#define等)的預編譯指令,在編譯開始前就先對原始的代碼文件進行調整。通過了預編譯以後,你寫的代碼其實已經有了很大的變化。編程

(2) 詞法分析後端

詞法分析是計算機科學中將字符序列轉換爲單詞(Token)序列的過程。進行詞法分析的程序或者函數叫做詞法分析器(lexical analyzer,簡稱lexer),也叫掃描器(Scanner),供語法分析器調用。瀏覽器

詞法分析階段是編譯過程的第一個階段,任務是從左到右以字符流的方式逐行掃描源代碼,而後根據構詞規則一一識別關鍵詞、標誌符、字面量、運算符等,並分割成一個個按順序排列的標記Token。編程語言

(3) 語法分析模塊化

語法分析是根據某種給定的形式文法對由單詞序列(如英語單詞序列)構成的輸入文本進行分析並肯定其語法結構的一種過程。進行語法分析的程序或者函數叫做語法分析器(parser),供語義分析調用。

語法分析階段是編譯過程的一個邏輯階段,任務是在詞法分析分割出來的標記Token的基礎上,將Token序列組合成各種語法短語如「程序」、「語句」、「表達式」等。

(4) 語義分析

語義分析是編譯過程的一個最實質性的階段,任務是對結構上正確的源代碼進行上下文有關性質的審查,進行類型審查。

其實通過語法分析以後就能初步獲得了抽象語法樹,樹上的每一個節點都是一個表達式,但此時還不肯定是否有意義。因而須要經過語義分析,遍歷整個抽象語法樹,把每一個節點的表達式都標識類型,而且驗證是否合法。

(5) 抽象語法樹

抽象語法樹(Abstract Syntax Tree,AST),是源代碼語法結構的一種抽象表示。它以樹狀的形式表現編程語言的語法結構,樹上的每一個節點都表示源代碼中的一種結構,以下圖所示:

從語法分析開始,就已經生成了初步的抽象語法樹。通過了語義分析以後,抽象語法樹又變得更加完善,自此最終版的抽象語法樹AST已經創建完成。

(6) 中間碼

通過前面幾個階段以後,咱們已經有了最終版的AST。可是該AST並不能完美運行在各個硬件平臺上,由於不一樣平臺的彙編處理都是不同的。

因而便在AST和多個平臺的彙編代碼中間,抽象出了一箇中間碼(Intermediate Representation),在中間碼的設計裏抹平了硬件平臺形成的差別。中間碼的強大之處在於跨平臺,與語言無關。

(7) 目標代碼

計算機是經過彙編指令來執行操做的,如移動到內存某個地址、位移多少個字節等。所以須要經過目標平臺的彙編器,由AST轉成的中間碼生成目標平臺的彙編代碼,這些纔是機器能讀懂的目標代碼。

3. 編譯前端與後端

前面介紹了這麼多編譯步驟,其實咱們能夠把中間碼當成一個分界線,中間碼之前的環節叫作編譯前端,中間碼之後的環節叫作編譯後端。

(1) 編譯前端

編譯前端包括預編譯、詞法分析、語法分析、語義分析、抽象語法樹等,專門用來處理語言專屬特性。雖然不一樣語言的詞法關鍵字、語法規則、語義分析的函數類型校驗可能都不同,甚至某些語言都沒有預編譯這個環節,但每一個語言均可以開發一套編譯前端,按照標準生成的統一中間碼就能夠無縫對接給任意編譯後端,這就是語言無關。

(2) 編譯後端

編譯後端這裏只包含了目標代碼生成部分,其實還應該包括將目標代碼連接成爲可執行文件的環節。編譯後端專門負責處理各個平臺的差別,根據不一樣語言生成的標準中間碼,生成對應的目標代碼,這就是平臺無關。

4. 編譯工具

(1) GCC

GCC(GNU Compiler Collection,GNU編譯器套裝),包含了編譯前端與編譯後端全部模塊。其中,編譯前端部分支持C、C++、Fortran、Pascal、Objective-C、Java等語言,編譯後端支持x8六、mips、Alpha、ARM、AVR、IA-6四、SPARC、PowerPC等30多種平臺。

GCC雖然被普遍的使用,但目前也面臨了危機。後起之秀的Clang / LLVM,大有全面趕超GCC的勢頭。

(2) Clang / LLVM

Clang是一個C++編寫、基於LLVM、發佈於LLVM BSD許可證下的C / C++ / Objective-C / Objective-C++ 的編譯器。那爲啥已經有了GCC後還要開發Clang呢?Clang相比於GCC有什麼優點呢?由於Clang是一個高度模塊化開發的輕量級編譯器,它的編譯速度快、佔用內存小、很是方便進行二次開發。

而有了Clang這個編譯器前端還不夠,因而就跟LLVM這個編譯器後端組合成一個完整的編譯器套件,以下圖所示:

5. WebAssembly在編譯環節的位置

前面說了這麼多,但仍是不知道WebAssembly處於編譯階段哪一個環節啊?心急吃不了熱豆腐,凡事都要對基礎知識有必定了解以後,才能茅塞頓開。

經過下圖你即可以一目瞭然WebAssembly所處的位置,它能作到像Java字節碼同樣,一次編譯處處運行,具備跨平臺特性。以此同時,做爲中間碼的WebAssembly直接省略編譯前端的步驟,而JavaScript須要實時編譯,相比之下性能優點顯著。

6. 寫在最後

若是WebAssembly不出現,那麼HTML、CSS、JavaScript將成爲前端領域的事實彙編語言,瀏覽器最終會把它們做爲「編譯目標」。WebAssembly的出現則提供了一個更好的選擇:接近原生的運算速度,不只擁有開源、兼容性好、跨平臺覆蓋廣等特性,還能夠藉此機會拋棄JavaScript的歷史遺留問題,何樂而不爲呢?

參考資料

  1. WebAssembly:解決 JavaScript 痼疾的銀彈?
  2. WebAssembly的過去、如今和將來
  3. 扯淡:大白話聊聊編譯那點事兒
  4. LLVM相比於JVM,有哪些技術優點?
  5. WebAssembly 系列(三)編譯器如何生成彙編
  6. WebAssembly入門:將字節碼帶入Web世界
  7. JavaScript是如何工做的:與WebAssembly比較及其使用場景
  8. LLVM編譯原理和使用

我的公衆號:前端開發升值記

相關文章
相關標籤/搜索