武建平 時 龍興 凌 明 曹 聞世
(東南大學國家專用集成電路系統工程技術研究中心,南京 210096)
Unicore架構下的Dalvik虛擬機優化
武建平 時 龍興 凌 明 曹 聞世
(東南大學國家專用集成電路系統工程技術研究中心,南京 210096)
基于Unicore架構,對Dalvik虛擬機進行了移植優化.通過分析Unicore架構下應用程序二進制接口與Dalvik虛擬機的平臺相關性,設計實現了jniArgInfo變量字段的布局以及與Dalvik虛擬機平臺相關的本地方法調用橋.在設計完成Unicore架構下的快速型解釋器入口函數、別名寄存器、匯編宏定義以及匯編版本快速型解釋器架構等組件的基礎上,結合虛擬機快速型解釋器的混合實現機制對Dalvik虛擬機進行了優化,并對優化后Dalvik虛擬機的兼容性、功能、性能進行了測試驗證.實驗結果表明,優化后的Dalvik虛擬機符合Android系統規范,虛擬機核心部件及Dalvik解釋器性能穩定,與優化前相比,系統每秒執行的字節碼數目提升達147%.與同類平臺的對比測試結果驗證了Dalvik虛擬機性能提升的合理性.
Dalvik虛擬機;Unicore;Android;本地方法調用橋;解釋器
近年來,隨著以智能手機[1]為代表的移動互聯終端的飛速發展,與之配套的智能操作系統(如Windows CE和Windows Mobile系列、蘋果公司的iOS等)開創了移動智能終端發展的新方向.2007年,Google公司正式發布了第一款 Android系統[2],它是為移動互聯終端打造的第一個開放性移動軟件平臺.為了創建更加開放的開發環境,Google公司組建了開放手機聯盟(open handset alliance,OHA)[3],使得設備制造商、處理器原廠、第三方應用開發商等業界產業鏈圍繞Android系統持續發展.從第一款Android手機發布至今不到5年的時間,Android系統已在移動智能終端領域占據了絕對領導地位.
當前,Android系統絕大部分是基于ARM處理器架構的,其主要原因在于:ARM處理器架構功耗較低,Android系統可基于ARM處理器架構進行全面的支持和優化.基于國產 Unicore架構的SoC(system on chip)芯片 SEP6200[4]面向嵌入式移動互聯設備,以Android系統為基礎軟件平臺.然而,Android系統并未針對Unicore架構進行支持和優化.
Dalvik虛擬機是Android系統應用程序運行的基礎,它通過執行特有的字節碼格式——Dalvik字節碼來完成對象生命周期、堆棧、線程、安全異常的管理以及垃圾回收等功能.它依賴于Linux內核的部分功能——線程機制和內存管理機制,能高效使用內存,且在CPU低速運行時性能良好.每個Android應用在底層均對應一個獨立的Dalvik虛擬機實例.虛擬機的執行引擎負責Dalvik字節碼流的解釋執行[5].Dalvik虛擬機的解釋器提供了多種實現方式,其中快速型解釋器提供了一種允許混合使用匯編語言和C語言來實現解釋例程的機制.與傳統Java虛擬機相比,Dalvik虛擬機的最大特點是擁有專用的Dex文件[6];相對于Class文件,Dex文件更緊湊,內存占用更小,同時Dalvik字節碼在執行性能上比Class字節碼更勝一籌.從執行流程分析,Dalvik虛擬機主要由加載器子系統、執行引擎和內存管理模塊組成.Dalvik虛擬機的實現離不開Dx工具、Dalvik字節碼指令集、運行時常量區等部分.
本文基于Unicore架構進行Android系統中核心模塊 Dalvik[7]虛擬機的移植與優化,使得 Android系統能夠流暢運行于SEP6200處理器平臺,主要圍繞Dalvik虛擬機的實現與優化2個方面展開.首先,通過分析Unicore架構下應用程序的二進制接口和Dalvik虛擬機的平臺相關性,設計了jniArgInfo變量字段的布局.然后,結合Unicore架構的特點,實現了本地方法調用橋.設計實現了基于Unicore架構的匯編版本快速型解釋器的多個組件,主要包括快速型解釋器入口函數、別名寄存器、匯編宏定義以及匯編版本快速型解釋器架構,并利用快速型解釋器的混合編程機制,通過別名寄存器、數據布局以及匯編型快速解釋器的構建,完成Dalvik虛擬機的優化.
Java語言本身具備平臺無關性,但Dalvik虛擬機引入的 JNI(Java native interface)機制[8-9]使得虛擬機的實現與平臺緊密關聯.Dalvik虛擬機可屏蔽平臺間的差異性,故Java語言編寫的Android應用程序可以在任何平臺上運行.在Dalvik虛擬機中,當Java方法通過JNI機制調用本地方法時,需要將Java方法中的參數傳遞給本地方法,而本地方法參數的傳遞在不同平臺下存在著各自的約束[10].為了在不同平臺上實現本地方法參數的傳遞,在JNI架構中設計了本地方法調用橋.
Unicore架構下,Dalvik虛擬機的移植實現關鍵在于本地方法調用橋的實現.它隸屬于JNI機制,與數據類型在內存中的對齊要求和函數調用規范相關.本節主要圍繞本地方法調用橋的實現展開,簡單介紹了 JNI機制及 Unicore架構下 ABI(application binary interface)中的數據類型布局、寄存器使用和函數調用規范.
Android應用框架層中的API(application port interface)通過 JNI機制與系統動態庫或 HAL(hardware abstract level)等本地代碼相關聯.這些本地方法通過Dalvik虛擬機中的一個工具庫nativehelper注冊到系統,在Java程序中調用這些本地方法時用native關鍵字聲明即可.
JNI機制的調用方法包括以下2個方面:Android系統提供的本地方法和應用程序中性能關鍵部分使用的本地方法.前者以系統動態庫的形式存在,后者以應用自帶動態庫的形式存在于 APK(Android package)中.JNI機制在 Android系統中的調用方法如圖1所示.

圖1 JNI機制在Android系統中的調用流程
JNI機制實現的核心數據結構是 JNINative-Method.該結構體包含JNI函數的名稱、參數和返回值的類型簽名以及JNI函數對應的本地語言(C/C++)的函數指針等重要成員.多個JNINativeMethod結構體變量組成的數組可以完整地描述一組本地方法,是連接Java方法和本地方法的橋梁.本地方法列表將作為參數傳遞給registerNativeMethods函數,該函數通過調用JNI機制提供的jniRegisterNativeMethods函數對本地方法進行注冊.至此,本地方法已注冊到系統,可供基于Java語言編寫的上層應用程序直接調用.
通過定制Unicore架構下的ABI,使得獨立編譯、匯編得到的代碼可以被正確地鏈接、執行.ABI主要包括存儲布局(數據類型布局)、寄存器的使用和函數調用規范3個方面的內容.
1.2.1 數據類型布局
Unicore采用小端(小印地安序)存儲,定義8 bit為 byte(字節)、16 bit為 half-word(半字)、32 bit為word(字),可尋址最小單位為byte.它采用load/store體系結構,對 byte,half-word,word數據的讀取和存儲分別由 ldb/std,ldh/sth,dw/stw等指令完成.除基本數據類型外,結構體、聯合、枚舉、數組等數據類型在內存中的布局也有各自的要求.對Unicore架構下的基本數據類型在內存中的對齊方式進行以下說明:所有數據類型對齊方式最大為4 byte對齊,包括大小為8 byte(64 bit)的 long long和double雙精度類型數據.與此對應的函數棧起始地址也是4 byte對齊.
1.2.2 寄存器的使用
Unicore體系結構提供了46個通用寄存器、1個程序計數器和6個狀態寄存器.與ARM體系結構相同,這些寄存器并非同時可見,不同操作模式決定著哪些寄存器可見.
同一時刻一種模式下可見的寄存器包括31個通用寄存器、1個程序計數器(PC)和1個或 2個狀態寄存器,寬度均為 32 bit.Unicore架構下的寄存器比ARM架構多一倍,這在 RISC(reduced instruction set computing)體系架構中占據一定的優勢.但這種優勢也是相對的.例如,在15個寄存器足夠使用的情況下,并不能體現31個寄存器的優勢.特定情況下可利用寄存器數目多的優勢為Unicore架構作進一步優化.各種模式下寄存器的使用由硬件決定,軟件層同樣存在著寄存器的使用規則[4].
1.2.3 函數調用規范
Unicore架構中的棧采用滿遞減棧,數據的對齊依賴于其在內存中的對齊方式.保存在棧中的局部變量會按照對齊方式對變量存放的位置進行調整,使其占用的空間最小.最佳方式是將局部變量存放在變量寄存器(R17~R25)中,此時,保存在寄存器中的變量讀取效率要比存放在棧中的變量高很多.
Unicore架構提供了若干指令以支持函數調用.最方便的方式是采用BL指令,它會自動將返回地址(當前PC地址后的第4個地址)壓入LR(連接寄存器)中,PC寄存器會得到即將被調用的函數的入口地址.使用BL的結果是將控制權轉交給被調用函數,棧和所有變量寄存器均為被調用函數服務.LR作為隱式參數傳遞給被調用函數,以保證函數的正確返回.
調用函數時應遵循相應的傳參規則,類似于ARM架構的ATPCS(ARM-thumb procedure call standard).在Unicore架構下,總是使用R0~R3傳遞前16 byte數據,其他參數則通過棧進行傳遞.傳參類型按以下規則進行:小于4 byte的類型提升為4 byte,保證符號位不變.將64 bit數據作為2個32 bit數據進行處理,并將這2個數據存放在連續的存參空間(依次為 R0,R1,R2,R3和棧)中,高 32 bit數據在后,低32 bit數據在前.存參空間被視為一段連續的地址空間,由寄存器和本地棧部分構成.將函數參數按照上述參數類型轉換規則轉換成以32 bit為單位的參數數據流,按由低到高的順序依次填充即可.
基本類型的最大數據寬度為64 bit,將它作為返回值時最多需要2個寄存器.在Unicore架構下,將標量類型作為返回值時的規則如下:小于或等于1 word的整形數據返回時,使用R0寄存器;64 bit整形數使用R0,R1寄存器,其中高32 bit數據在R1中;單精度數據使用f0返回;雙精度數據使用f0,f1返回,高32 bit數據在f1中.
利用JNI機制調用本地方法,實現參數傳遞的機制被稱為本地方法調用橋.其實現的關鍵在于如何填充jniArgInfo變量字段以得到準確的??臻g大小以及如何將參數傳遞給本地方法.填充好的jniArgInfo變量將被作為參數傳遞給dvmPlatformInvoke函數,該函數用于處理參數傳遞并完成本地方法調用.
jniArgInfo變量攜帶了參數傳遞時本地棧需要預留的空間大小信息,它的設計與Unicore架構下棧入口地址的對齊方式以及數據在棧中的對齊方式相關.Unicore架構下棧入口地址為4 byte對齊,jniArgInfo只需要記錄3類信息:參數個數是否合法、返回值類型和參數個數.jniArgInfo變量字段的布局如圖2所示.圖中每個字母代表1 bit,具體定義如下.
S位(bit31):該位為符號位,用來標識參數個數是否合法.受Dex文件限制,參數個數不能大于0xFFFF.當參數個數超過0xFFFF時,S位會被寫入“1”而被置位;
R位(bit28~bit30):用來表示本地方法返回類型.
H位(bit0~bit27):用來記錄參數在存參空間的本地棧部分所占空間大小(以32 bit為單位).由于參數個數最大為0xFFFF,因此需要將H位重新布局.重新布局后的結果如圖3所示.

圖2 jniArgInfo布局

圖3 H bit布局
圖3中,Z位為預留位,可以清零;A位記錄了傳遞參數時本地棧需要預留的空間.jniArgInfo變量字段的填充在dvmPlatformInvokeHints函數中進行,實現的核心是解析signature類型簽名(表示調用方法的返回值類型、參數類型等信息)以得到jniArgInfo變量的S位、R位和A位.當參數個數大于0xFFFF時,則會調用dvmAbort異常函數中止虛擬機,其原因是當一個本地方法的參數數目超過0xFFFF時,即使符合語法規則也已經不是一個正常的本地方法.
實現本地方法調用橋的關鍵部分包括參數傳遞、本地方法調用及返回,這些功能均由dvmPlatformInvoke函數實現.實現流程如圖4所示.

圖4 dvmPlatformInvoke函數的實現流程
本地方法調用橋的核心功能是將解釋器棧中的參數傳遞給本地方法棧,進行本地方法調用.參數的傳遞過程如圖5所示.

圖5 本地方法的參數傳遞示意圖
Mterp解釋器[11]是Dalvik虛擬機執行引擎的核心.在沒有實現JIT時,Mterp解釋器充當了執行引擎的角色.Dalvik虛擬機為Mterp解釋器提供了多種實現方式,包括調試型、可移植型和快速型解釋器.本文主要通過別名寄存器來存儲關鍵的變量數據;構建匯編宏定義以表示具有特定意義的常用操作;構建匯編版本的解釋例程以實現匯編版本快速型解釋器,對Dalvik虛擬機進行優化.
在Unicore架構下,使用匯編實現快速型解釋器時,寄存器需要遵守EABI(embedded application binary interface)使用規則.在Mterp解釋器中,需要經常使用幾個特定的變量或數據,可以利用EABI寄存器使用規則為它們分配空閑、合適的寄存器,最大限度地減少內存訪問.這些變量并不在同一函數內,因為如果它們在同一函數內,編譯器即可為它們分配更加合理的寄存器,而無需利用EABI規則.因此,將與這些變量相關的函數采用匯編語言重寫,可以提升解釋執行的效率.事實上,以dvm-MterpStdRun函數作為入口函數的Mterp解釋器,采用匯編語言重新編寫,可以最大限度地利用別名寄存器的優勢,將所需要的數據直接寫入指定寄存器或從指定寄存器中讀取.此時,別名寄存器充當著全局變量的角色.
匯編版本快速型解釋器構建了一系列匯編宏定義,以表示特定的常用操作,這些操作構成了解釋例程的基本功能.匯編宏的構建為編寫匯編解釋例程帶來了極大便利,使得在實現解釋例程時可以更多地關注解釋例程本身的功能.部分匯編宏的定義見表1.

表1 匯編宏定義表
匯編版本快速型解釋器的入口函數與C語言版本的入口函數保持一致,均為dvmMterpStdRun函數.匯編版本中的入口函數需要完成以下操作:①本地棧入棧,保存現場;② 將本地棧堆棧指針SP保存到glue結構體中的bailPtr變量中,作為返回地址;③ 初始化rGLUE,rPC,rFP,rIBASE別名寄存器;④ 檢測glue結構體中的entryPoint成員,判斷是否為常規字節碼,若不是則進行返回、異常等相應處理,若是則從rPC指向的字節碼開始加載、解釋執行.對于入口函數,匯編版本快速型解釋器必須實現其出口函數,當執行到return等字節碼時則會調用出口函數,從而使解釋器退出連續解釋執行的狀態.出口函數完成如下操作:①恢復本地棧堆棧指針SP;②將第2個參數作為返回值返回;③本地棧出棧,恢復現場.
在匯編版本快速型解釋器中,為了使字節碼連續執行,在每個解釋例程的尾部都會對下一條字節碼進行預取操作,這與其他解釋器的實現一致.但其他解釋器是通過調用解釋例程、查表來確定入口地址的,查表意味著內存存取操作.在匯編版本快速型解釋器中,則可以通過巧妙的設計跳過此操作(見圖6).匯編版本快速型解釋器的解釋例程限制在64 byte空間內.若64 byte無法完成解釋例程功能,則在dvmAsmSisterStart函數開始的地方(即附加段)繼續解釋工作,2段代碼間通過條件或無條件跳轉連接.256個解釋例程按照編碼大小從dvmAsmInstructionStart函數的地址開始依次排列,其中dvmAsmSisterStart函數的起始地址為64 byte對齊,不足64 byte的解釋例程用空指令填充至64 byte.每一個解釋例程的起始地址均為64 byte對齊,這種對齊方式與Cache行大小相匹配,可以加速解釋例程的執行.與可移植型解釋器和C語言快速型解釋器相比,匯編版本快速型解釋器具有如下優勢:①可利用別名寄存器加速常用變量的存取;②解釋例程描述的功能與匯編語言描述的功能接近,存在大量位段數據的存取操作,使得匯編語言的執行效率明顯高于高級語言;③ 通過對解釋例程巧妙設計,避免了確定入口地址時的查表操作,利用代碼段緩沖行對齊的特點,最大限度提升了解釋執行效率.

圖6 匯編版本快速型解釋器的解釋例程框架
下面從2個方面對Unicore架構下的Dalvik虛擬機性能進行測試驗證.首先,將匯編版本快速型解釋器與C語言版本快速型解釋器、可移植型解釋器的性能進行比較,分析性能差異的原因.然后,將SEP6200處理器和S3C6410平臺[12]下Dalvik虛擬機優化前后的性能進行對比分析.測試硬件平臺參數見表2.測試軟件選用專業虛擬機性能測試軟件 CaffeineMark[13].測試項目包括 Sieve,Loop,Logic,String,Float,Method 和 Overall[14].測試結果與CPU主頻相關,與內存大小無關.所有測試結果均為多次測試結果的平均值.

表2 對比測試軟硬件平臺參數
表3列出了可移植型解釋器、C語言版本快速型解釋器和匯編版本快速型解釋器三者的對比數據.由表可知,可移植型解釋器與C語言版本快速型解釋器均為thread分發機制,兩者均需通過查表確定下一個解釋例程的入口地址.但前者的每個解釋例程入口地址為標簽,解釋例程之間通過goto語句直接跳轉至標簽;后者的每個解釋例程對應一個函數,解釋例程之間通過函數調用首尾相連.由于函數調用比goto語句執行耗時更長,因此,后者的性能略低于前者.從測試結果來看,前者比后者整體性能提高約6%.

表3 Dalvik虛擬機解釋器的性能對比 字節碼/s
匯編版本快速型解釋器的執行速度是C語言版本的2.47倍,其原因在于:① 別名寄存器的使用可以減少對內存的訪問次數,提升解釋例程的性能.②匯編版本解釋器架構下,可以不經過查表就能獲取下一個解釋例程的入口地址;而在C語言版本快速型解釋器中,則需通過查表操作才能確定下一個解釋例程的入口地址.
對比測試平臺為S3C6410平臺.軟、硬件平臺參數信息對比見表2.
測試數據包括C語言版本快速型解釋器和匯編版本快速型解釋器在2個平臺下Dalvik虛擬機的性能數據以及優化前后性能的對比數據.
由表3可知,與C語言版本快速型解釋器相比,Unicore架構下的Dalvik虛擬機采用匯編優化后,整體性能提升高達147%.2款平臺的對比實驗結果顯示:基于S3C6410平臺,與C語言版本快速型解釋器相比,匯編版本快速型解釋器可實現2.56倍的性能(即程序執行速度)加速比.該結果比在SEP6200平臺下采用匯編優化后,與C語言版本快速型解釋器相比能達到的性能加速比(2.47倍)略高.與C語言版本快速型解釋器的性能進行對比是為了具體量化基于SEP6200平臺優化前后Dalvik虛擬機的性能提升幅度.與S3C6410平臺下匯編版本快速型解釋器的性能數據進行對比,是為了驗證SEP6200平臺下優化后的Dalvik虛擬機的性能提升是否合理.優化前SEP6200平臺下虛擬機的性能較S3C6410平臺下虛擬機的性能略高,尤其是Sieve,Float子項數據更為明顯,說明SEP6200平臺下虛擬機的整點、浮點運算性能更高.鑒于Unicore匯編指令集的因素,匯編優化后并沒有延續優化前的所有優勢,但SEP6200平臺下虛擬機的總體性能與S3C6410平臺下虛擬機的總體性能相當,充分驗證了本文針對Unicore架構下Dalvik虛擬機提出的優化方案的有效性.
本文在Unicore架構下完成了Dalvik虛擬機的移植.重點分析了Dalvik虛擬機與CPU處理器架構相關的部分,包括虛擬機的 JNI機制以及Unicore架構的ABI.實現了本地方法調用橋,構建了Unicore架構下匯編版本快速型解釋器的各個組件,并利用快速型解釋器提供的匯編語言和C語言的混合解釋機制,對Unicore架構下的Dalvik虛擬機進行了性能優化.實驗結果顯示,無論是優化前后的縱向對比還是與同類平臺的橫向對比,本文提出的Dalvik虛擬機優化方案均能明顯提升虛擬機性能.
[1]Wikipedia.Mobile operating system[EB/OL].(2011-06-10)[2011-11-15].http://en.wikipedia.org/wiki/Mobile_operating_system.
[2]Wikipedia.Android(operating system)[EB/OL].(2011-06-10)[2012-01-13].http://en.wikipedia.org/wiki/Android_(operating_system).
[3]Open Handset Alliance.Open handset alliance[EB/OL].(2010-09-20)[2011-12-14].http://en.wikipedia.org/wiki/Open_Handset_Alliance.
[4]Prochip Corporation.SEP6200 設計文檔[EB/OL].(2010-12-11)[2012-01-14].http://www.prochip.com.cn/product_show.asp?detailid=27.
[5]Lee Y M,Tak B C,Maeng H S,et.al.Real-time Java virtual machine for information appliances[J].IEEE Transactions on Consumer Electronics,2000,46(4):949-957.
[6]Google Corporation..dex—Dalvik executable format[EB/OL]. (2011-06-10)[2011-11-25].http://source.android.com/tech/dalvik/dex-format.html.
[7]Chang C W,Lin C Y,King C T,et al.Implementation of JVM tool interface on Dalvik virtual machine[C]//Proceedings of2010International Symposium on VLSI Design Automation and Test(VLSI-DAT).Hsin Chu,Korea,2010:143-146.
[8]Vladislav Tcheprasov.Template-generated JNI[J].Journal of C&C++Users,2004,22(8):38-39.
[9]Bi Lingyan,Wang Weining,Zhong Haobin,et al.Design and application of remote control system using mobile phone with JNI interface[C]//Proceedings of2008International Conference on Embedded Software and Systems Symposia.Beijing,China,2008:416-419.
[10]Qi Minglong,Guo Qingping.Implementing and invoking a remote object calling native methods via RMI-IIOP and JNI[C]//Proceedings of2004International Symposium on Distributed Computing and Applications to Business,Engineering and Science.Wuhan,China,2004:451-456.
[11]Ogata Kazunori,Komatsu Hideaki,Nakatani Toshio.Bytecode fetch optimization for a Java interpreter[C]//Proceedings of the10th International Conference on Architectural Support for Programming Languages and Operating Systems.New York,USA,2002:58-67.
[12]Samsung Corporation.S3C6410 application processor[DB/OL].(2008-04-01)[2011-12-16].http://www. samsung. com/global/business/semiconductor/product/application.
[13]Pendragon Software Corporation.CaffeineMark 3.0 information[EB/OL].(1997)[2011-11-21].http://www.benchmarkhq.ru/cm30/info.html#Overview.
[14]Google Corporation.Compatibility test suite[EB/OL].(2011-06-10)[2012-01-11].http://source.android.com/compatibility/cts-intro.html.
Optimization of Dalvik virtual machine based on Unicore architecture
Wu Jianping Shi Longxing Ling Ming Cao Wenshi
(National ASIC System Engineering Research Center,Southeast University,Nanjing 210096,China)
Based on the Unicore architecture,the Dalvik VM(virtual machine)is transplanted and optimized.First,the relationships between the application binary interfaces of Unicore and Dalvik VM platform are analyzed,and the layout of jniArglnfo's variable field and JNICallbridge(Java native interface Callbridge)which relates with the Dalvik VM are implemented.After several components of the fast interpreter,which includes the entry functions,alias registers,key assembly macro definitions and architecture in assembly version based on Unicore,are implemented,the Dalvik VM is optimized with the mixed mechanism advantage of the fast interpreter.The compatibility,function and performance of the optimized Dalvik VM are tested and verified.The experimental results show that,compared with the system before optimization,the Dalvik VM based on the Unicore architecture fully complies with the Android system.The core partitions and the whole Dalvik interpreter are robust and run steadily.The number of executed bytecode is speedup by 147%per second,and the rationality of the performance gains are verified by comparing with other similar platforms.
Dalvik virtual machine;Unicore;Android;native interface Callbridge;interpreter
TN302
A
1001-0505(2013)01-0017-07
10.3969/j.issn.1001-0505.2013.01.004
2012-05-22.
武建平(1977—),男,博士生;凌明(聯系人),男,博士,副教授,trio@seu.edu.cn.
國家科技重大專項資助項目(2009ZX01031)、江蘇省"青藍工程"資助項目.
武建平,時龍興,凌明,等.Unicore架構下的Dalvik虛擬機優化[J].東南大學學報:自然科學版,2013,43(1):17-23.[doi:10.3969/j.issn.1001-0505.2013.01.004]