亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

KVM的執行引擎(上) — 棧和幀

2019-11-18 16:25:55
字體:
來源:轉載
供稿:網友

接下來的兩篇將介紹在KVM中字節是如何執行的,這是KVM中比較核心的內容,分為兩部分來講,本篇先介紹虛擬機中的棧和幀是如何實現的。

 

首先來看一些全局指針,在頭文件kvm/vmcommon/h/interPRet.h中定義有以下結構:

Word-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
strUCt GlobalStateStruct { 
    BYTE*         gs_ip; /* Instruction pointer (program counter) */
    cell*         gs_sp; /* Execution stack pointer */
    cell*         gs_lp; /* Local variable pointer */
    FRAME         gs_fp; /* Current frame pointer */
    CONSTANTPOOL  gs_cp; /* Constant pool pointer */
};

這五個變量就像CPU中的寄存器一樣,在KVM的運行過程中起到非?;A性的作用。它們分別是程序計數器、執行棧指針、局部變量指針、當前幀指針和當前常量池指針。

java虛擬機為每一個線程開設一個棧,棧中存儲的數據以“幀”為單位,虛擬機在調用一個新的方法時,會向棧中壓入一個新幀,幀內數據是這個方法的運行狀態,Java字節碼的執行總是在當前幀內進行,方法運行結束時這個幀會被彈出。所以這個??梢苑Q為“方法棧”,幀可以稱為“方法幀”。

按照Java虛擬機的規范,一個幀應由三個部分組成:局部變量區,操作數棧和幀數據區。每個幀的局部變量區和操作數棧的大小都可能不一樣,要依方法本身的龐大程度而定,但在調用一個方法時,可以根據這個方法的字節碼計算出所需要的局部變量區和操作數棧的大小。規范對幀數據區的大小沒有規定,幀數據區的大小和內容可由虛擬機實現來決定。

局部變量區:

局部變量區一般會位于幀中最前面(即地址最?。┑奈恢?,它包含了對應方法的參數和局部變量,一般情況下,它的大小是向4字節對齊的,每4字節是一個“字”,變量以“字”為單位來存入。在它的最前面順序存放的是對應方法的參數,類型為int、float、reference和returnAddress的參數占一個“字”,類型為byte、short和char類型的參數對被轉化為int型,所以也占一個字;long和double類型的值要占用兩個字。當然,“字長”選為多少是由虛擬機實現自己來決定的,不是一定要選4字節為一個字,如果選8字節構成一個字的話,所有值都只占一個字,更加整齊,但是浪費了很多空間。

如果方法不是靜態的,那么虛擬機會自動將方法所在對象的句柄存在局部變量區中索引為0的位置,真正的參數從位置1開始存;而如果方法是靜態的,它就與具體的對象沒有關系,所以不必存放對象句柄,參數從位置0開始存放。

在局部變量區接下來的空間中,虛擬機可以按照任意的方式來存貯方法內的局部變量。

操作數棧:

操作數棧的作用相當于CPU中的通用寄存器,由于Java虛擬機是一臺虛擬的機器,它沒有真正的寄存器,而Java虛擬機也沒有選擇與CPU相似的方式來模擬通用寄存器,而是選擇了另一種方法 — 使用棧,Java指令所使用的操作數都從操作數棧中得到。

某方法在被調用的時候,同樣可計算出它需要多大的操作數棧,所以在一個幀中,操作數棧的大小也是固定,而它的位置可以由實現來決定,不過在接下來KVM的實例中我們會發現,把操作數棧放在幀的最后面(地址最大)的地方是一個好辦法。

幀數據區:

幀數據是由虛擬機實現任意設計的,通常它都被用來實現常量池解析和異常處理等等。

 

 

下面來看一看,在KVM中如何實現棧和幀。

數據結構:

在頭文件kvm/vmcommon/h/frame.h中定義了棧和幀的結構:

/* STACK */
struct stackStruct {
    STACK    next;
    short    size;
    short    xxunusedxx; /* must be multiple of 4 on all platforms */
    cell     cells[STACKCHUNKSIZE];
};
typedef struct stackStruct*         STACK;
 

每一個stackStruct結構體的變量就是一個Java?;騄ava棧的一部分,因為每一個stackStruct結構的大小是固定的,如果不夠用,可以得用next指針來擴展成鏈表。size是本結構體的大小,xxunusedxx是剩余空間,cells則是實際的存貯空間。

每一個線程開始的時候都會生成一個新的stackStruct,在每一次壓入新幀的時候會查看剩余空間是否夠用,如果不夠用,還會再生成新的stackStruct。

frameStruct這個結構的大小是固定的,它并不是一個幀,而只是“幀數據區”,前面說過,由于局部變量區和操作數棧的大小都不固定,所以整個幀的大小也是不固定的。幀的空間是在調用方法的時候臨時計算出來的,然后在當前線程的棧中申請,frameStruct結構的指針占據其中的一個字,其余空間都給局部變量區和操作數棧用。

KVM中棧和幀的模型如下:(為理解方便,暫不考慮棧要擴展的情況)

當棧中只有一個幀時,棧的結構如圖所示:

 KVM的執行引擎(上) — 棧和幀(圖一)

當棧中只有一個幀時,幀的低字節區是局部變量,接下來會有一個字(4字節)指向幀數據區結構體,再接下來的空間就是操作數棧。

只有一幀時,幀中各部分的結構很明晰,但如果多于一幀時,情況就會有些復雜,下面看當再壓入一幀時的圖示:

KVM的執行引擎(上) — 棧和幀(圖二)

這個圖或許跟想像中的不一樣,兩幀數據之間出現了重疊。圖中畫出了一條虛線,這條虛線的位置是上一幀結束的位置,但是卻沒有成為新的一幀開始的位置,新的一幀在這之前就開始了。重疊的區域究竟是什么,可以讓兩幀共用呢?

當一個方法在執行時,如果一個指令需要參數,解釋器會到操作數棧里去裝載參數,如果這時的指令是調用一個方法的話(比如invokevirtual或invokestatic),待調用方法的參數應已經順序存在于操作數棧中,在執行調用指令的時候,這些參數被彈出,成為調用指令的參數,由于操作數棧在幀的最后面,所以這些參數后面再沒有本幀的有效數據。這些參數在當前幀的操作數棧中的排列順序與在新幀的局部變量區中的排列順序是一樣的,而且在新幀中,局部變量區在新幀的最前面,參數列表又在局部變量區的最前面,所以這部分數據是可以重用的,不會丟失有用的信息。

 

程序實現:

壓入幀和彈出幀的函數在源文件kvm/vmcommon/src/frame.c中:

void pushFrame(METHOD thisMethod);

void popFrame();

pushFrame()函數的一些關鍵代碼如下:

1    int thisFrameSize = thisMethod->frameSize;
2    int thisArgCount = thisMethod->argCount;
3    int thisLocalCount = thisFrameSize - thisArgCount;
4    …
5    cell* prev_sp = getSP() - thisArgCount; /* Very volatile! */
6    …
7    newFrame = (FRAME)(getSP() + thisLocalCount + 1);
8    …
9    /* Initialize info needed for popping the stack frame later on */
10    newFrame->previousSp = prev_sp;
11    newFrame->previousIp = getIP();
12    newFrame->previousFp = getFP();
13    …
14    /* Initialize the frame to execute the given method */
15    newFrame->thisMethod = thisMethod;
16    newFrame->syncObject = NIL; /* Initialized later if necessary */
17    …
18    /* Change virtual machine registers to execute the new method */
19    setFP(newFrame);
20    setSP((cell*)(newFrame + 1) - 1);
21    setIP(thisMethod->u.java.code);
22    setCP(thisMethod->ofClass->constPool);
23    ...

L1-L3分別讀出幀的大小、參數列表的大小和本幀實際申請空間的大?。◤膸袦p去與上一幀復用的部分);

sp是當前棧內的指針,也是操作數的指針,在新的一幀壓入之前,sp應指向操作數棧中最后一個參數的位置,所以L5中prev_sp所取得的是上一幀中函數參數列表的首地址,也就是新幀開始的位置,以后新方法返回的時候,新幀被彈出,這里應是操作數棧的當前位置,也就是sp的位置,函數的返回值要存放到這里;

L7為新幀申請了空間;

L10-L12為保存調用之前的寄存器狀態;

L19-L22為寄存器賦新值。

popFrame()函數比較簡單,主要就是調用了下面這個宏來恢復調用前寄存器的值:

#define POPFRAMEMACRO                                                          
    setSP(getFP()->previousSp);    /* Restore previous stack pointer */        
    setIP(getFP()->previousIp);    /* Restore previous instruction pointer */  
    setFP(getFP()->previousFp);    /* Restore previous frame pointer */        
    setLP(FRAMELOCALS(getFP()));   /* Restore previous locals pointer */       
    setCP(getFP()->thisMethod->ofClass->constPool);


/* FRAME (allocated inside execution stacks of threads) */
struct frameStruct {
    FRAME    previousFp; /* Stores the previous frame pointer */
    BYTE*    previousIp; /* Stores the previous program counter */
    cell*    previousSp; /* Stores the previous stack pointer */
    METHOD   thisMethod; /* Pointer to the method currently under execution */
    STACK    stack;      /* Stack chunk containing the frame */
    OBJECT   syncObject; /* Holds monitor object if synchronized method call */
};
typedef struct frameStruct*            FRAME;
進入討論組討論。

(出處:http://www.49028c.com)



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品手机在线| 国产精品自拍小视频| 久久久噜噜噜久久| 国产精品美女久久久久av超清| 欧美成人剧情片在线观看| 国产精品视频1区| 91国自产精品中文字幕亚洲| 精品国产福利在线| 欧美色欧美亚洲高清在线视频| 日韩欧美在线观看视频| 亚洲国产99精品国自产| 亚洲а∨天堂久久精品喷水| 国产精自产拍久久久久久| 久久精品国产91精品亚洲| 日韩电影在线观看中文字幕| 久久久伊人欧美| 国产精品永久免费视频| 热草久综合在线| 97免费在线视频| 亚洲精品日韩久久久| 久99久在线视频| 日本乱人伦a精品| 九九热视频这里只有精品| 国产精品自产拍在线观看| 亚洲美女在线看| 亚洲资源在线看| 亚洲精品二三区| 国产精品一区二区三区久久| 亚洲一区二区福利| 亚洲人成电影在线播放| 91视频国产精品| 日韩在线视频线视频免费网站| 九九热r在线视频精品| 欧美在线播放视频| 亚洲娇小xxxx欧美娇小| 日韩久久精品成人| 麻豆国产精品va在线观看不卡| 精品女同一区二区三区在线播放| 亚洲精品视频免费在线观看| 久久久久久久久爱| 久久久国产精品亚洲一区| 欧美性猛交xxxx黑人| 日韩中文字幕在线观看| 精品欧美aⅴ在线网站| 欧美性猛交xxxx偷拍洗澡| 久久久亚洲网站| 欧美夫妻性生活xx| 久久天天躁狠狠躁夜夜爽蜜月| 69久久夜色精品国产69| 久久久亚洲精品视频| 欧美午夜美女看片| 亚洲aa在线观看| 91av免费观看91av精品在线| 日韩最新av在线| 欧美日韩aaaa| 57pao国产成人免费| 亚洲欧美日韩在线高清直播| 大胆欧美人体视频| 精品女同一区二区三区在线播放| 欧美一级在线亚洲天堂| 国产91精品久久久| 精品久久久久久久久久| 亚洲精品美女久久久| 日韩美女视频免费在线观看| 97久久久久久| 欧美日韩精品中文字幕| 国产精品精品视频一区二区三区| 亚洲人a成www在线影院| 欧美成人精品一区| 一级做a爰片久久毛片美女图片| 亚洲偷熟乱区亚洲香蕉av| 国产一区二中文字幕在线看| 亚洲一二三在线| 久久久在线免费观看| 欧美极品少妇xxxxⅹ喷水| 亚洲第一精品福利| 日韩中文字幕精品| 亚洲最大的成人网| 欧美日韩国产丝袜另类| 国产精品第8页| 神马国产精品影院av| 国产精品爱啪在线线免费观看| 海角国产乱辈乱精品视频| 国产精品久久久久久久9999| 日韩美女福利视频| 久久久久久久999精品视频| 亚洲综合第一页| 综合国产在线观看| 国产精品第一第二| 日本精品免费一区二区三区| 亚洲国产天堂久久国产91| 久久久久999| 日韩视频精品在线| 中文字幕视频一区二区在线有码| 国产欧美一区二区三区在线看| 欧美专区第一页| 国产91精品最新在线播放| 91久久久久久久一区二区| 久久久亚洲国产天美传媒修理工| 国产精品r级在线| 热久久免费视频精品| 日韩av网站在线| 国产精品视频网| 都市激情亚洲色图| 一区二区三区视频免费在线观看| 久久精品一本久久99精品| 国产美女搞久久| 国产精品美腿一区在线看| 中文字幕日韩av| 永久免费看mv网站入口亚洲| 91av在线不卡| 欧美在线视频网站| 国产精品自拍偷拍视频| 久久影院资源网| 久久深夜福利免费观看| 97精品视频在线播放| 欧美性高潮床叫视频| 91性高湖久久久久久久久_久久99| 国产精品羞羞答答| 久久夜色撩人精品| 播播国产欧美激情| 中文字幕av一区中文字幕天堂| 国产精品美女免费| 亚洲精品网站在线播放gif| 久久精品99久久久久久久久| 色偷偷av亚洲男人的天堂| 国产高清视频一区三区| 国产在线一区二区三区| 精品一区二区三区四区在线| 成人久久18免费网站图片| 92看片淫黄大片看国产片| 亚洲www在线| 欧美在线亚洲一区| 国产精品久久久久久亚洲影视| 一区二区三区视频在线| 日韩精品中文字幕在线观看| 午夜精品视频网站| www.国产精品一二区| 伊人久久免费视频| 国产精品一久久香蕉国产线看观看| 在线视频免费一区二区| 懂色av中文一区二区三区天美| 亚洲欧美另类人妖| 亚洲精品国产suv| 精品国产福利视频| 国产精品九九久久久久久久| 欧美国产日韩xxxxx| 亚洲永久免费观看| 亚洲精品久久久久久久久久久| 日韩动漫免费观看电视剧高清| 青青草99啪国产免费| 日韩成人中文字幕在线观看| 亚洲第一页中文字幕| 97色在线视频| 国内精品久久久久伊人av| 国产欧美日韩中文字幕| 亚洲成人a级网| 国产欧美精品在线播放| 国产欧美最新羞羞视频在线观看| 欧美日韩亚洲视频| 中日韩美女免费视频网址在线观看| 久久频这里精品99香蕉| 亚洲成年人影院在线| 91久久精品日日躁夜夜躁国产|