目标機的記憶體管理
要允許目标機的binaries在不同平台執行,未必需要重新編譯檔案。如果源檔案是以big-endian格式編碼的,且如果給定平台是little-endian,那麼目标機上的Run-time應該負責相應的轉換。
虛拟機要支援可移植性特征,需要在軟體中實作完整的記憶體保護。
當目标機的Run-time被調用時,它從本地作業系統配置設定記憶體來為單個應用程式建構人工的位址空間。此位址空間确切地被分成三部分:text 部分、heap 部分、stack 部分。位址依次從低到高,text部分起始位址為0。
在編譯時test部分的位址是固定的,而stack和heap部分的位址大小是可調節的。
虛拟機支援指令行選項,允許調整stack和heap的尺寸,要求是非負值。運作時還檢查确定stack不會溢出到heap部分,或溢出到被禁止的位址空間頂部。
保護本地平台要做的另一件事是,固定一定數量的有效記憶體到位址空間。一旦配置設定了text、heap和stack位址後,立刻做這件事。Unix系統使用sbrk()函數。
當虛拟機初始載入一個應用程式到記憶體,它做一次性檢查,确定程式的binary編碼指令的合法性。這種一次性檢查就是位元組碼校驗(Bytecode Verification)。虛拟機檢檢視指令操作數是否有正确的值,還檢查确定位址符号沒有越界,所有的指令操作代碼均有效。
要消除記憶體延遲(Memory Latency)造成的一些危險,最好是把Run-time載入到實體記憶體。在目标機建立位址空間之前,目标機做一個調用,檢視空閑的實體記憶體大小,如果有效的實體記憶體不足,則虛拟機不啟動。
最為複雜的是heap管理。可以考慮使用顯示記憶體管理模式。理由如下:
1)大多數垃圾收集器的實作都采用了多線程環境,耗用不少CPU周期。如果目标機不是多線程環境呢?
2)虛拟機的設計目标是可移植性、簡單性、高性能。類似與BDW收集器之類的保守垃圾收集器并不簡單,不能馬上就實作移植。從本質上講,垃圾收集器需要run-time系統做額外的工作來跟蹤已配置設定的記憶體。這些額外的工作引入了額外的指令,降低了系統性能。
機器設計
中央處理器能以基于寄存器或基于Stack的機器來實作。基于寄存器的處理器,如Intel的奔騰處理器;而基于Stack的處理器,如Harris半導體的RTX32P,它有兩個片上Stack來執行基本的操作。
基于Stack的處理器在嵌入式領域往往更為流行,因為它們可支援更小的程式,更受限的資源。比如一個基于Stack的處理器指令如IADD,從Stack彈出兩個整數,然後求和,并把和壓入Stack,指令如下:
ADD $R1, $R2, $R3
此指令求得$R2和$R3的和,并放入$R1。
基于Stack的IADD指令隻需一個單位元組就可完成該工作。而基于寄存器的ADD指令至少需要四個位元組。
是以顯然基于Stack的機器編譯程式所需的時間比基于寄存器的機器編譯時間更短。
基于Stack的計算機執行函數調用也更高效。因為函數參數本身就存放在Stack内。而基于寄存器的計算機,其函數參數必須存取,并手動放入到Stack,需要做更多的工作。
基于Stack的計算機其上下文切換耗費資源也更小。而基于寄存器的計算機,上下文切換前必須手動儲存所有寄存器的狀态,RISC架構往往有大量的寄存器,其上下文切換需要集中記憶體操作。而基于Stack的計算機則沒有這些問題。
并非基于寄存器的架構就一無是處,它有一個更大的優勢:更快。寄存器位于CPU内,存取值操作非常塊。Intel的新64處理器,如Itanium,有上百個片上寄存器,而基于Stack的處理器,幾乎總是從記憶體存取資料,這顯然比較慢。
比較表
————————————————————————————————————————————————
--------- 基于Stack的處理器 基于寄存器的處理器
Benefits 更小的記憶體占用 基本操作非常快
更快的函數調用 (整體性能更好)
更快的上下文切換 執行更透明
Costs 基本操作比較慢 memory-intensive上下文切換
work-intensive函數調用