自己動(dòng)手實(shí)現(xiàn)一個(gè)有JIT的虛擬機(jī)
由于發(fā)這篇專欄的時(shí)候我還在讀高二,沒學(xué)過編譯原理,不過我還是去查閱了資料,并試著以我自己的理解實(shí)現(xiàn)JITVM。

當(dāng)你已經(jīng)熟練了掌握一門編程語言之后,可能你并不滿足當(dāng)前一些語言,于是你覺得自制一門語言,它可以是解釋型,也可以是編譯型的,目的都是更好的實(shí)現(xiàn)及針對(duì)化的去滿足使用需求,比如一眾小游戲基本都有自己的腳本,哪怕再簡單的那種,也是對(duì)自己游戲開發(fā)效率、生態(tài)的一種擴(kuò)充(開發(fā)mod),同時(shí)刪掉一些不太想要的功能,比如游戲腳本我不想讓他操作file類,或者runcmd,這些操作都是極為危險(xiǎn)的,更何況有人還要發(fā)到steam上的創(chuàng)意工坊,于是我們才要自己實(shí)現(xiàn)一門比腳本語言性能更好的語言。
然而,當(dāng)你每開發(fā)一個(gè)新的項(xiàng)目,就會(huì)對(duì)你當(dāng)前的語言有不同的要求,無疑拖慢了開發(fā)效率并降低了兼容度,而實(shí)現(xiàn)多種語言共同使用一套標(biāo)準(zhǔn)的虛擬機(jī)就顯得尤為重要。同時(shí)考慮到性能,我們還要加入JIT。
這里以JVM的原理為例,因?yàn)槲也]有深入學(xué)過JVM,這里簡化來講,如有不對(duì)還請(qǐng)指出:
我們都知道CPU只能運(yùn)行編譯后的機(jī)器碼,而java編譯后是bytecode,即字節(jié)碼,而我們必須意識(shí)到,沒有編譯過程的代碼,一定以某種方式去解釋該代碼才能運(yùn)行,所以jvm的底層本質(zhì)還是會(huì)有if去判斷代碼的,并且我們無需擔(dān)心if的效率,畢竟if只是寫多了很亂而已,效率其實(shí)并不低。
以上便是一個(gè)VM最最基本、也是最重要的過程--解釋非本機(jī)代碼,并實(shí)現(xiàn)方法,也就是說,字節(jié)碼不直接參與到CPU的執(zhí)行過程。
而JIT(Just in time compilation)即時(shí)編譯,才是我們要重點(diǎn)實(shí)現(xiàn)的,也是提高性能的根本。
那么,我們?cè)撊绾稳?shí)現(xiàn)一個(gè)JIT呢?
我們假設(shè)有以下需求的(偽)代碼:
static void startGame(String gamePath)
{
Process.Start(gamePath);
}
首先我們進(jìn)行分析:
1.這是一個(gè)static的void,是靜態(tài)的,void代表不返回,該代碼是過程
2.參數(shù)為string字符串為常量,甚至實(shí)際的時(shí)候有可能我們會(huì)寫死這個(gè)程序的路徑
3.調(diào)用了VM的基本庫process,也是靜態(tài)過程start,傳入string
這代碼確實(shí)很像C#
通過分析我們發(fā)現(xiàn),改該過程可以被簡化成以下形勢(shì):
startGame("YuanShen.exe");
簡化為
Process.Start("YuanShen.exe");
假設(shè)process類我們可以編譯成本機(jī)代碼,那么以上代碼完全可以被編譯成本機(jī)代碼(數(shù)據(jù)地址)的形式。
這整個(gè)過程,就是JIT做的--把盡可能本機(jī)化的代碼全部編譯成當(dāng)前平臺(tái)的本機(jī)代碼,并把引用放進(jìn)代碼池,運(yùn)行到這個(gè)地方時(shí),直接運(yùn)行本機(jī)代碼,而不是在VM內(nèi)加減寄存器、調(diào)用VM方法來進(jìn)行實(shí)現(xiàn)。
于是我們得到JIT一個(gè)大概的工作流程:
(代碼標(biāo)準(zhǔn)化/統(tǒng)一為字節(jié)碼)->詞法分析->語法分析->語義分析->執(zhí)行流分析->本機(jī)優(yōu)化->本機(jī)代碼拼接-->鏈接VM內(nèi)數(shù)據(jù)地址->合成本機(jī)代碼
其實(shí)不難看出,這個(gè)過程在編譯階段就執(zhí)行過一遍,但是他會(huì)比字節(jié)碼編譯多一個(gè)本機(jī)優(yōu)化,JIT的意義不僅是提高代碼的執(zhí)行效率,也能在不同的平臺(tái)之上通過獲取相關(guān)信息進(jìn)行針對(duì)性優(yōu)化,使得生成的本地代碼更快更適應(yīng)當(dāng)前平臺(tái)。
下一篇我們先來實(shí)現(xiàn)基礎(chǔ)部分,實(shí)現(xiàn)一個(gè)最簡單的VM并在自己的VM運(yùn)行最簡單的代碼--hello world!

今天先說到這里吧,手機(jī)碼字,錯(cuò)誤請(qǐng)指出。