指令集是虛擬機(jī)中最底層也是最核心的部分,java程序中的變量賦值、函數(shù)調(diào)用等所有操作最后都要被轉(zhuǎn)化為一條條的指令來(lái)執(zhí)行。
指令集是在Java虛擬機(jī)規(guī)范中定義的,各種虛擬機(jī)實(shí)現(xiàn)要給予精確的實(shí)現(xiàn),下面就來(lái)介紹一下指令集的分類以及在KVM中是如何實(shí)現(xiàn)的。
在頭文件kvm/vmcommon/h/interPRet.h中有如下對(duì)指令集種類的定義:
以及每條指令的名字:
Java虛擬機(jī)的指令集非常多,大概有200種左右,本篇不詳細(xì)介紹每一條指令的功能和參數(shù),只選取幾個(gè)典型的指令作為例子,介紹它們是如何實(shí)現(xiàn)的。
KVM中,所有指令的實(shí)現(xiàn)都放在kvm/vmcommon/src/bytecodes.c中,每一條指令都遵從如下的形式:
{operations}部分是該指令的具體實(shí)現(xiàn)。
整個(gè)bytecodes.c文件其實(shí)是一個(gè)switch分支結(jié)構(gòu)中的cases部分,這個(gè)文件中定義了所有的case。這個(gè)文件會(huì)被源文件kvm/vmcommon/src/execute.c所包含,execute.c中定義有一個(gè)方法
void SlowInterpret(ByteCode token);
函數(shù)結(jié)尾處的幾個(gè)標(biāo)簽是指令完成后會(huì)跳轉(zhuǎn)到的地方。
依據(jù)Java虛擬機(jī)規(guī)范,虛擬機(jī)指令可以分為裝載和存儲(chǔ)指令、運(yùn)算指令、類型轉(zhuǎn)換指令、對(duì)象創(chuàng)建與操縱指令、操作數(shù)棧管理指令、控制轉(zhuǎn)移指令、方法調(diào)用和返回指令、拋出和處理異常指令、實(shí)現(xiàn)finally指令和同步指令等10類,下面從中選取幾個(gè)簡(jiǎn)單的指令來(lái)看一看它們是如何設(shè)計(jì)的:
1、ICONST_0
說(shuō)明:
無(wú)參數(shù),向操作數(shù)棧中壓入int型常量0。
實(shí)現(xiàn)代碼:
GlobalState.gs_sp是當(dāng)前幀內(nèi)操作數(shù)棧的指針,ICONST_0指令要做的只是把指針向后移動(dòng)一個(gè)字(注意是“字”而不是“字節(jié)”),然后給新字賦值為0;最后程序計(jì)數(shù)器ip自加1,表明沒(méi)有跳轉(zhuǎn),接著執(zhí)行下一條指令。
2、DSTORE
說(shuō)明:
本指令帶有一個(gè)字節(jié)的參數(shù)offset,作用是從操作數(shù)棧中讀取一個(gè)double型的值(雙字)并存放到局部變量區(qū)中的offset和offset+1位置。
實(shí)現(xiàn)代碼:
首先從程序計(jì)數(shù)器的下一個(gè)字節(jié)中取出目標(biāo)位置的偏移量index,然后從操作數(shù)棧中彈出兩個(gè)字分別作為double型數(shù)的底位和高位存入局部變量lp所指向的區(qū)域中的合適位置。
3、I
說(shuō)明:
無(wú)參數(shù),將操作數(shù)棧中的當(dāng)前操作數(shù)由int型轉(zhuǎn)換為long型。
實(shí)現(xiàn)代碼:
由于long比int表示的范圍大,所以在擴(kuò)展時(shí)多出來(lái)的高位只是用于符號(hào)擴(kuò)展。先從操作數(shù)棧中取出int型整數(shù)并把它作為一個(gè)long型,如果定義了宏BIG_ENDIAN,說(shuō)明操作數(shù)棧中的存儲(chǔ)規(guī)則是高字節(jié)在前,這時(shí)要把value的值向后移一個(gè)字作為低字來(lái)用,高字用于作符號(hào)擴(kuò)展;如果操作數(shù)棧中是低位在前的話,原位置中的字不用動(dòng),只要把下一個(gè)字作符號(hào)擴(kuò)展即可。最近,由于當(dāng)前操作數(shù)由一個(gè)字變?yōu)閮蓚€(gè)字,所以sp要自加1。
4、LMUL
說(shuō)明:
無(wú)參數(shù);從棧中彈出兩個(gè)long型數(shù),相乘,然后將所得long型結(jié)果壓回棧。
實(shí)現(xiàn)代碼:
先從操作數(shù)棧中分別取出兩個(gè)雙字長(zhǎng)的長(zhǎng)整型數(shù),使用ll_mul()宏把它們相乘(這個(gè)宏的實(shí)現(xiàn)是依賴于操作系統(tǒng)的),然后再把相乘的結(jié)果寫(xiě)入棧中。整個(gè)操作從棧中彈出了四個(gè)字而壓入兩個(gè),在過(guò)程中指針sp都沒(méi)有變過(guò),所以最后要把sp向前移兩個(gè)字。
以下作為例子的都是一些簡(jiǎn)單的指令,但并不是所有指令都這樣簡(jiǎn)單,像對(duì)象操作、異常處理和方法調(diào)用幾類指令都十分的復(fù)雜,本篇只是演示指令的原理,所以不介紹太復(fù)雜的指令。
(出處:http://m.survivalescaperooms.com)
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注