本篇文章是Lua設計與實現專欄的第三篇,主要結合了《Lua設計與實現》書中的第五章(虛擬機),以及lua5.3源碼進行一些總結,由於原書中主要是基於lua5.1進行書寫的,所以可能會有跟書中列舉代碼不一致的地方,不過大體上是保持一致的。
同時,本文虛擬機的概念和類型劃分的內容主要參考了這篇blog的,裡面講的挺詳細的。
虛擬機基本概念
虛擬機指藉助軟體系統對物理機器指令執行進行的一種模擬。首先,對於物理機器的執行,主要是機器從內存中fetch指令,通過匯流排傳輸到CPU,然後進行解碼、執行、結果存儲等步驟。既然虛擬機是對其進行的一種模擬,那麼也逃不過以下幾個特點:
- 將源碼編譯成VM所能執行的位元組碼。
- 位元組碼格式(指令格式),例如三元式、四元式、波蘭式等。
- 函數調用的相關棧結構,函數的出入口和傳參方式。
- 指令指針,類似於物理機的指令寄存器(EIP)。
- 虛擬CPU。 instruction dispatcher。
- 取指:通過IP fetch下一條指令
- 解碼:對指令進行翻譯,得到指令類型,並且解析其操作數。
- 執行:跳到對應邏輯塊進行執行。
棧式虛擬機和寄存器式虛擬機
雖然虛擬機的實現都逃不過以上幾步,但是以具體實現來看,又分為兩大類:棧式和寄存器式。
棧式虛擬機
採用棧式虛擬機的語言有JVM、CPython以及.Net CLR等。 它的概念很簡單,就是所有的指令執行,都是基於一個操作數棧的。你想要執行任何指令時,對不起,得先入棧,然後算完了再給我出棧。流程如下圖: