lua源碼:開始

文件根據實現功能的不一樣,能夠分爲四部分:編程

 

1虛擬機運轉的核心功能

lapi.c            C語言接口
lctype.c        C標準庫中ctype相關實現
ldebug.c      Debug接口
ldo.c            函數調用以及棧管理
lfunc.c         函數原型及閉包管理
lgc.c            垃圾回收
lmem.c        內存管理接口
lobject.c      對象操做的一些函數
lopcodes.c  虛擬機的字節碼定義
lstate.c        全局狀態機
lstring.c       字符串池
ltable.c        表類型的相關操做
ltm.c            元方法
lvm.c            虛擬機api

lzio.c            輸入流接口數組

 

2源代碼解析以及預編譯字節碼

lcode.c         代碼生成器
ldump.c       序列化預編譯的 lua 字節碼
llex.c            詞法分析器
lparser.c       解析器安全

lundump.c   還原預編譯的字節碼數據結構

 

3內嵌庫

lauxlib.c        庫編寫用到的輔助函數庫
lbaselib.c      基礎庫
lbitlib.c         位操做庫
lcorolib.c      協程庫
ldblib.c         Debug庫
linit.c            內嵌庫的初始化
liolib.c          IO庫
lmathlib.c     數學庫
loadlib.c       動態擴展庫管理
loslib.c         OS庫
lstrlib.c         字符串庫
ltablib.c        表處理庫 
閉包

4可執行的解析器,字節碼編譯器

lua.c              解釋器
luac.c            字節碼編譯器
lua核心部分僅包括lua虛擬機的運轉。lua虛擬機的外在數據形式是一個lua_State結構體,取名State大概
編程語言

意爲lua虛擬機的當前狀態。函數式編程

 

閱讀源代碼的次序(從外到內)

首先、閱讀外圍的庫是如何實現功能擴展的,這樣能夠熟悉Lua公開API。沒必要陷入功能細節。
而後、閱讀API的具體實現。
函數

Lua對外暴露的API能夠說是一個對內部模塊的一層封裝,這個層次還沒有觸及核心,但能夠對核心代碼有個初步的瞭解。
以後、能夠開始瞭解LuaVM的實現。
接下來就是分別理解函數調用、返回,string 、table 、metatable 等
如何實現。
debug 模塊是一個額外的設施,但能夠幫助你理解 Lua 內部細節。
最後是 parser 等等編譯相關的部分。
性能

垃圾收集將是最難的部分,可能會花掉最多的時間去理解細節。

 

Lua的C函數以堆棧的形式和Lua虛擬機交換數據,由一系列API從L中取出值,通過一番處理,壓回L中的堆棧。

Lua棧給C函數留的默認空間很小,默認狀況下只有20。當你要在Lua的棧上留下大量值時,務必用luaL_checkstack擴展堆棧。由於處於性能考慮,Lua和棧有關的API都是不檢查棧溢出的狀況的。

在實現上,UserData只是對象結構從TString換成了Udate

 

Lua使用table做爲統一的數據結構。 用 table來表示Lua中的一切數據結構是Lua語言的一大特點。 爲了效率,Lua的官方實現,又把table的儲存分爲數組部分和哈希表部分。 

Table按照Lua語言的定義,須要實現四種基本操做:讀、寫、迭代和獲取長度。Lua中並無刪除操做,而僅僅是把對應鍵位的值設置爲nil

Table的數組部分操做和C語言數組沒有什麼不一樣,不須要特別處理。 

Lua實現複雜數據結構,大量依賴給table附加一個元表(metatable)來實現。

 

你能夠很容易的建立出一個Lua虛擬機對象,不一樣的Lua虛擬機之間的工做是線程安全的,由於一切和虛擬機相關的內存操做都被關聯到虛擬機對象中,而沒有利用任何其它共享變量。 

Lua的虛擬機核心部分,沒有任何的系統調用,是一個純粹的黑盒子,正確的使用Lua,不會對系統形成任何干擾。這其中最關鍵的一點是,Lua讓用戶自行定義內存管理器,在建立Lua虛擬機時傳入,這保證了Lua的整個運行狀態是用戶可控的。

從Lua的使用者的角度看,global_state 是不可見的。咱們沒法用公開的API取到它的指針,也不須要引用它。global_State裏面有對主線程的引用,有註冊表管理全部全局數據,有全局字符串表,有內存管理函數,有GC須要的把全部對象串聯起來的相關信息,以及一切Lua在工做時須要的工做內存。 經過lua_newstate建立一個新的lua虛擬機時,第一塊申請的內存將用來保存主線程和這個全局狀態機。 Lua的實現儘量的避免內存碎片,同時也減小內存分配和釋放的次數。它採用了一個小技巧,利用一個LG結構,把主線程 lua_State 和 global_state 分配在一塊兒。 

Lua中的數據能夠這樣分爲兩類:值類型和引用類型。值類型能夠被任意複製,而引用類型共享一份數據,由GC負責維護生命期。Lua使用一個聯合 union value來保存數據。 

Lua的程序運行是以線程爲單位的。每一個Lua線程能夠獨立運行直到自行中斷,把中斷的信息留在狀態機中。每條線程的執行互不干擾,能夠獨立延續以前中斷的執行過程。Lua的線程和系統線程無關,因此不會爲每條Lua線程建立獨立的系統堆棧,而是利用本身維護的線程棧,內存開銷也就遠小於系統線程。 

lua是用longjmp處理與c互相函數調用的問題。

 

若是說C++式的面向對象編程是把一組函數綁定到特定數據類型上的話,那麼閉包能夠說是把一組數據綁定到特定函數上。 閉包是函數和upvalue的結合體。



Lua中的函數調用有兩種,一種是標準的函數調用,它會須要生成新的一層調用棧,執行函數流程,而後彈出調用棧返回。另外一種叫作尾調用,它是對標準函數調用的優化。尾調用不生成新的調用棧,而不復用當前的。在大多數函數式編程語言中,都須要對尾調用作特別優化。由於函數式語言特別依賴函數的層層調用,甚至用尾調用的方式來作循環。傳統方式每次函數調用都須要生成新的棧幀,容易形成棧溢出。 尾調用能夠看做C中的goto。

參考:

《lua源碼賞析》

如何學習 Lua VM 的源碼?https://www.zhihu.com/question/20617406

《 Structure and Interpretation of Computer Programs 》

相關文章
相關標籤/搜索