之前聽尤大說懂編譯原理就能夠隨心所欲,因而簡單地研究了一點(nai)點(nai)的編譯原理,感受本身能夠隨心所欲了。。。前端
經典的《編譯原理》一書當中,開篇大概講解了關於編譯原理的一些基本概念和編譯器的基本結構:java
編譯器: 一個編譯器就是一個程序,它能夠閱讀某一種語言編寫的程序,並把該程序翻譯成爲一個等價的、用另外一種語言(目標語言)編寫的程序。 解釋器,另外一種常見的語言處理器,它並不經過翻譯的方式生成目標程序。從用戶的角度看,解釋器直接利用用戶提供的輸入執行源程序中指定的操做。node
詞法分析(lexical analysis) 詞法分析器讀入源程序中的字符序列,將他們組織爲具備詞法含義的詞素,生成並輸出表明這些詞素的 詞法單元(token) 序列。編程
語法分析(syntax analysis) 語法分析或稱解析(parsing)。語法分析器由詞法分析器生成的各個詞法單元建立樹形的中間表示。該中間表示給出了詞法分析產生的詞法單元流的語法結構。一個經常使用的表示法是語法樹 (syntax tree) , 樹中的每一個內部結點表示一個運算,而該結點的子結點表示該運算的份量。性能優化
語義分析 (semantic anlaysis) 語義分析器使用語法樹和符號表中的信息來檢查源程序是否和語言定義的語義一致。 語義分析完成語法檢查以及相關的自動類型轉換。編程語言
中間代碼生成ide
代碼優化 機器無關的代碼優化步驟試圖改進中間代碼,以便生成更好的目標代碼。性能
代碼生成 以源代碼的中間表示形式爲輸入,並把他映射到目標語言。優化
雖然說,通常把上面的流程看做基本的編譯原理,可是,大部分編程語言的編譯器都和這個流程有些不一樣。ui
這裏參考了另一本書 -- 《WebKit 技術內幕》。
從 C/C++語言提及。編譯器會將咱們編寫的代碼編譯爲本地代碼(適合當前計算機運行的指令集)。
當須要執行程序時, CPU 能夠直接執行這些本地代碼,無需其餘處理。
再來看看腳本語言 Python。通常地,當須要執行 Python 程序時,由解釋器直接解釋執行開發者寫的代碼。
接下來看看 Java。Java 首先是和 C++同樣的編譯階段,不一樣的是編譯生成了字節碼。字節碼的特色是與平臺無關,能夠運行在不一樣的操做系統上。 Java 的運行環境中,使用 Java 虛擬機加載字節碼,而後:
這裏說了一個 JIT 的概念,百度了一下,大體特色以下:
最後看看前端的主角 JavaScript。JavaScript 本是一個解釋型腳本語言。由於早期是由解釋器解釋執行,即將源代碼轉爲抽象語法樹,而後在抽象語法樹上解釋執行。 在 JavaScript 引擎的發展中,爲了提升性能,引入了 Java 虛擬機和 C++編譯器中的衆多技術。如今 JavaScript 引擎的執行過程大體是:
關於 V8 的身世和衆多的黑科技咱們不去追究,反正一提到 V8 引擎,知道很牛逼就是了。 相對上面提到的典型的 JavaScript 引擎,V8 的編譯採用了比較激進的方式,將抽象語法樹經過 JIT 技術直接轉換成本地代碼。 這麼作能夠減小抽象語法樹到字節碼的轉換時間,同時也帶了一些問題:
對於這些問題,V8 也在解決:5.9 版本開始新增了一個 Ignition 字節碼解釋器。關於這個話題,下面引用一段話,更多細節能夠看這裏。
Ignition + TurboFan 的組合,就是字節碼解釋器 + JIT 編譯器的黃金組合。這一黃金組合在不少 JS 引擎中都有所使用,例如微軟的 Chakra,它首先解釋執行字節碼,而後觀察執行狀況,若是發現熱點代碼,那麼後臺的 JIT 就把字節碼編譯成高效代碼,以後便只執行高效代碼而再也不解釋執行字節碼。蘋果公司的 SquirrelFish Extreme 也引入了 JIT。SpiderMonkey 更是如此,全部 JS 代碼最初都是被解釋器解釋執行的,解釋器同時收集執行信息,當它發現代碼變熱了以後,JaegerMonkey、IonMonkey 等 JIT 便登場,來編譯生成高效的機器碼。
《編譯原理》 很經典,很好的一本書,翻譯很精準。好比,詞法分析的結果 token,書中翻譯爲詞法單元,可是國內不少的博客會都翻譯爲令牌,這就很使人費解。
《WebKit 技術內幕》 僅僅看了 JavaScript 引擎一段,感受做者不太用心。有錯別字,好比把整型寫成了整形。最尷尬的是不少的語句不通。感受是直接懟的谷歌翻譯的結果。最騷的是,這是國人原著而非翻譯書籍。。。 後來百度了一下,聽說這本書的內容是根據做者的我的博客整理的。