亚洲成年人黄色一级片,日本香港三级亚洲三级,黄色成人小视频,国产青草视频,国产一区二区久久精品,91在线免费公开视频,成年轻人网站色直接看

處理值類型的制作方法

文檔序號(hào):11160868閱讀:380來源:國(guó)知局
處理值類型的制造方法與工藝

實(shí)施例一般涉及用于在編程語(yǔ)言內(nèi)支持和/或利用值類型結(jié)構(gòu)體的技術(shù)。



背景技術(shù):

計(jì)算機(jī)語(yǔ)言提供許多不同的方法來創(chuàng)建聚合類型(aggregate type)。例如,諸如Java之類的語(yǔ)言提供具有標(biāo)識(shí)(identity)的異構(gòu)聚合(例如,“類”)和具有標(biāo)識(shí)的同構(gòu)聚合(例如,“數(shù)組”)。標(biāo)識(shí)由諸如唯一地識(shí)別對(duì)象的標(biāo)識(shí)號(hào)(例如,存儲(chǔ)器地址)之類的每個(gè)實(shí)例化對(duì)象所包括的頭部信息來實(shí)現(xiàn)。然而,對(duì)象標(biāo)識(shí)具有占用空間(footprint)和性能成本,這是Java具有存儲(chǔ)在適當(dāng)?shù)奈恢?、在方法調(diào)用期間在不使用引用的情況下通過值傳遞、并且不包括頭部的原生類型(primitive type)的主要原因。這與引用類型相反,引用類型由指針訪問、使用在方法調(diào)用期間通過值傳遞的引用來表示、并且包括頭部。對(duì)于不具有許多字段來分?jǐn)傊С謽?biāo)識(shí)所需的額外成本的小對(duì)象來說,支持標(biāo)識(shí)的成本是最難以負(fù)擔(dān)的。

例如,考慮具有類型為整型(int)的x和y字段的Point類。在實(shí)施方式中,每個(gè)Point對(duì)象可以包括額外的對(duì)象頭部(8到16字節(jié))和引用(4到8字節(jié))的Point對(duì)象數(shù)組意味著這些8字節(jié)的數(shù)據(jù)(對(duì)于x和y整數(shù))占用20到32字節(jié)的堆空間。此外,遍歷該數(shù)組意味著對(duì)于所訪問的每個(gè)Point對(duì)象的指針解引用。這破壞了數(shù)組的內(nèi)在局部性(inherent locality)并且限制了程序性能。

程序員經(jīng)常采取比如將Point數(shù)組表示為兩個(gè)整型數(shù)組(一個(gè)用于x并且一個(gè)用于y)的技巧來避免這些成本,但是該方法犧牲了封裝性(和可維護(hù)性)只是為了補(bǔ)回標(biāo)識(shí)的性能損失。一種方法是顯著擴(kuò)大語(yǔ)言支持的原生的數(shù)量。然而,(如果有可能的話)可能難以預(yù)期高效地解決放在程序員面前的每個(gè)問題將需要的原生類型。因此,落在原生類型和對(duì)象的領(lǐng)域之間的結(jié)構(gòu)體將對(duì)程序員有很大益處。

附圖說明

在附圖的圖中通過示例的方式而不是限制的方式示出了本發(fā)明,在附圖中相似的附圖標(biāo)記指代相似的要素,其中:

圖1示出了可以實(shí)踐本文所描述的技術(shù)的示例性計(jì)算架構(gòu)。

圖2是示出了適于實(shí)現(xiàn)本文所描述的方法和特征的計(jì)算機(jī)系統(tǒng)的一個(gè)實(shí)施例的框圖。

圖3示出了根據(jù)實(shí)施例的以框圖形式的示例性虛擬機(jī)存儲(chǔ)器布局。

圖4示出了根據(jù)實(shí)施例的以框圖形式的示例性幀。

圖5示出了根據(jù)實(shí)施例的用于在容器中存儲(chǔ)值類型的過程。

圖6示出了根據(jù)實(shí)施例的用于訪問值類型的過程流。

圖7是示出了可以實(shí)現(xiàn)本發(fā)明的實(shí)施例的計(jì)算機(jī)系統(tǒng)的框圖。

具體實(shí)施方式

在下面的描述中,出于解釋的目的,闡述了許多具體細(xì)節(jié)以便提供對(duì)本發(fā)明的深入理解。然而,顯而易見,可以在沒有這些具體細(xì)節(jié)的情況下實(shí)踐本發(fā)明。在其他實(shí)例中,公知的結(jié)構(gòu)和設(shè)備以框圖形式示出,以避免不必要地混淆本發(fā)明。

本文根據(jù)以下提綱描述實(shí)施例:

1.0總體概述

2.0示例性操作環(huán)境

2.1示例性類文件結(jié)構(gòu)

2.2示例性虛擬機(jī)架構(gòu)

2.3加載、鏈接和初始化

3.0值類型概述

3.1用例

3.2示例性值類型特性

3.3示例性限制

3.4指針管理

3.5示例性定義

3.6示例性用法

3.7示例性實(shí)現(xiàn)細(xì)節(jié)

3.8示例性字節(jié)碼和類型描述符

3.9裝箱和對(duì)象互操作性

3.10示例性代碼

3.11附加的示例性選項(xiàng)

3.12類型到值類型的遷移

3.13更新字段的值

4.0修改后的加載進(jìn)程

5.0存儲(chǔ)考慮

5.1存儲(chǔ)過程流

6.0原子操作

7.0硬件概述

8.0擴(kuò)展和替代

9.0第一附加公開

10.0第二附加公開

1.0總體概述

本文所描述的技術(shù)經(jīng)常使用來自Java編程語(yǔ)言、Java虛擬機(jī)(“JVM”)和Java運(yùn)行環(huán)境的術(shù)語(yǔ)和定義。然而,構(gòu)想的是所描述的技術(shù)可以結(jié)合任何編程語(yǔ)言、虛擬機(jī)架構(gòu)或運(yùn)行環(huán)境來使用。因此,例如諸如“方法”之類的按Java術(shù)語(yǔ)描述的用辭可與諸如“函數(shù)”之類的其他用辭互換。此外,術(shù)語(yǔ)“方法”還與術(shù)語(yǔ)“類方法”或“對(duì)象方法”同義。方法是由名稱指代并且可以在使得方法的代碼被執(zhí)行的程序中的各種點(diǎn)處調(diào)用(援用)的一組代碼或代碼塊。

在實(shí)施例中,值類型是遵循“像類一樣編程,像整型一樣工作”原則的一種類別的聚合體。因此,像類一樣,值類型可以由程序員按照被命名的、類型成分(字段)、行為(方法)、隱私(訪問控制)、編程初始化(構(gòu)造函數(shù)(constructor))等來定義。然而,像原生類型(諸如整型)一樣,值類型不包含頭部信息并且被有效地當(dāng)作用戶定義的原生。因此,當(dāng)可行時(shí),值類型被存儲(chǔ)為扁平化的表示并且在方法之間通過值傳遞。因此,與對(duì)象相比,通過不要求指針被解引用以訪問值類型實(shí)現(xiàn)了速度改進(jìn),并且通過不要求值類型存儲(chǔ)頭部信息實(shí)現(xiàn)了存儲(chǔ)改進(jìn)。然而,實(shí)施例自由地以許多方式實(shí)現(xiàn)值類型的方面,這些方式中的一些方式可以違背“像類一樣編程,像整型一樣工作”原則。因此,本文所描述的值類型的特征可以被分開實(shí)現(xiàn)、作為整體實(shí)現(xiàn)或者無限制地以任何組合實(shí)現(xiàn)。

然而,為了實(shí)現(xiàn)值類型,存在若干考慮。一個(gè)考慮是如何在源語(yǔ)言和/或虛擬機(jī)的指令集(當(dāng)適用時(shí))中顯現(xiàn)(surface)值類型。例如,由于值類型不包含具有標(biāo)識(shí)信息的頭部,因此依賴于標(biāo)識(shí)的許多特征要么對(duì)于值類型必須被禁用,要么在值類型的背景下必須被分配新含義。作為另一示例,附加的指令和/或關(guān)鍵字可以被添加到源語(yǔ)言/虛擬機(jī)指令集以定義和利用值類型。節(jié)3.0“值類型概述”及其相關(guān)小節(jié)一般涉及如何在源語(yǔ)言和/或虛擬機(jī)的指令集中顯現(xiàn)值類型的問題。

另一個(gè)考慮是如何在諸如虛擬機(jī)的運(yùn)行環(huán)境之類的計(jì)算機(jī)系統(tǒng)的工作存儲(chǔ)器內(nèi)處理值類型的存儲(chǔ)。如上文提到的,旨在以扁平化的表示來存儲(chǔ)值類型。因此,例如如果對(duì)象具有存儲(chǔ)值類型的字段,則旨在將該值類型在沒有指針間接尋址(pointer indirection)的情況下存儲(chǔ)在適當(dāng)?shù)奈恢谩W鳛榱硪皇纠?,?dāng)值類型被加載到棧幀(stack frame)中的局部變量中時(shí),該值類型被扁平地存儲(chǔ)在表示局部變量的容器中。然而,因?yàn)橹殿愋涂梢跃哂锌勺兊某叽?,所以存在容器可能需要被調(diào)整尺寸以便容納特定的值類型的情況。這造成了性能問題,因?yàn)闉槿萜髦匦路峙鋬?nèi)存可能帶來大量開銷,尤其是當(dāng)重新分配經(jīng)常被執(zhí)行的時(shí)候。

因此,在一些實(shí)施例中,實(shí)現(xiàn)優(yōu)化以對(duì)存儲(chǔ)值類型的成本設(shè)定界限。例如,虛擬機(jī)的驗(yàn)證器可以定義若干指派規(guī)則,當(dāng)接收到在容器中放置值類型的指令時(shí)檢查這些指派規(guī)則。例如,驗(yàn)證器可以阻止將被分配為針對(duì)一種值類型的容器用于存儲(chǔ)具有不同尺寸的值類型。因此,阻止了虛擬機(jī)不斷地重新分配容器以適配不同的值類型。作為另一示例,如果值類型超出了尺寸閾值并且被確定為是不可變的,則虛擬機(jī)可以選擇在所管理的堆存儲(chǔ)器上存儲(chǔ)值類型并且替代地在容器中存儲(chǔ)對(duì)堆的引用。因此,阻止了虛擬機(jī)引起多次復(fù)制過大的值類型的開銷。例如,如果局部變量被放置在操作數(shù)棧上,則該局部變量可以通過引用而不是通過值被復(fù)制。然而,由于值類型是不可變的,因此對(duì)終端用戶而言,指令的行為(從語(yǔ)義的角度)無法與其中值類型被存儲(chǔ)并通過值傳遞的情況分辨開來。這可能導(dǎo)致訪問的時(shí)間增加,但是對(duì)于大的值類型來說,復(fù)制花費(fèi)的時(shí)間量可能大大超過去除指針遍歷的益處。節(jié)5.0“存儲(chǔ)考慮”及其相關(guān)小節(jié)一般涉及存儲(chǔ)優(yōu)化和性能的問題。

在一些實(shí)施例中,值類型是不可變的,意味著值類型(至少?gòu)慕K端用戶的視角)不能以分段的方式更新。這類似于諸如Java之類的一些語(yǔ)言怎樣允許由變量保持的整數(shù)被替換,但是不向用戶提供允許整數(shù)的單個(gè)位改變值的指令。因此,在值類型的背景下,不可變性意味著值類型僅可以作為整體被替換。然而,即使當(dāng)值類型為不可變時(shí),值類型也仍然可以被存儲(chǔ)在可變的變量或容器中。在變量、字段或容器的背景下,不可變性暗示著由該變量或容器保持的值不能被替換(例如,被凍結(jié))。

另一考慮是如何阻止值類型在被多個(gè)線程訪問時(shí)的撕裂。假設(shè)值類型被存儲(chǔ)在諸如許多虛擬機(jī)實(shí)現(xiàn)方式的堆之類的共享存儲(chǔ)器中,由于多個(gè)線程同時(shí)訪問值類型,因此存在競(jìng)爭(zhēng)狀況(race condition)的風(fēng)險(xiǎn)。由于值類型旨在充當(dāng)諸如原生整型之類的整個(gè)值,因此當(dāng)?shù)谝痪€程試圖更新存儲(chǔ)值類型的容器并且第二線程在第一線程完全結(jié)束更新之前讀取該容器時(shí),結(jié)構(gòu)撕裂發(fā)生。結(jié)果,第二線程在容器中遇到部分是舊值并且部分是新值的值類型。為了阻止結(jié)構(gòu)撕裂,技術(shù)被應(yīng)用以使得存儲(chǔ)和加載操作是原子的。然而,由于值類型是用戶定義的,因此執(zhí)行原子訪問的合適方法可能基于值類型的尺寸和/或用途以及底層計(jì)算機(jī)系統(tǒng)的硬件能力而變化。例如,一些中央處理單元(CPU)支持針對(duì)各種尺寸(例如,64位、128位、256位等)的原子更新和/或事務(wù),但是這些硬件指令不能考慮可能被用于值類型的每個(gè)尺寸。因此,因?yàn)橹殿愋涂梢源笥诘讓佑布С值淖畲笤哟鎯?chǔ)器轉(zhuǎn)移,所以結(jié)構(gòu)撕裂變得有可能,這是因?yàn)?例如)對(duì)4成分值的寫入可以被拆成兩個(gè)64位寫入,而該值的讀取可以被拆成兩個(gè)64位讀取。因此,如果讀取和寫入這二者同時(shí)執(zhí)行,則有可能遇到作為舊值和新值的混合的值類型。

在實(shí)施例中,使用若干技術(shù)來優(yōu)化針對(duì)值類型的原子操作。例如,如果硬件指令可用于執(zhí)行原子操作,則該指令是優(yōu)選的,因?yàn)橛布?shí)現(xiàn)的技術(shù)與軟件實(shí)現(xiàn)的技術(shù)相比一般具有更好的性能。此外,在某些情形中,原子操作可以被繞過,諸如當(dāng)被訪問的字段為不可變時(shí)。在一些實(shí)施例中,當(dāng)值類型的字段被頻繁訪問時(shí),值類型被修改以將該字段放置在由指針引用訪問的單獨(dú)的容器中。通過創(chuàng)建更新后的值的拷貝并且切換指針,可以相對(duì)快地執(zhí)行對(duì)通過指針訪問的字段的原子更新。因此,通過修改值類型的結(jié)構(gòu),當(dāng)執(zhí)行原子訪問時(shí)可以獲得提高的性能。節(jié)6.0“原子操作”一般針對(duì)涉及原子操作的問題。

2.0示例性操作架構(gòu)

圖1示出了可以實(shí)踐本文所描述的技術(shù)的示例計(jì)算架構(gòu)100。

如圖1中所示,計(jì)算架構(gòu)100包括源代碼文件101,源代碼文件101由編譯器102編譯為表示要被執(zhí)行的程序的類文件103。類文件103然后由執(zhí)行平臺(tái)112加載并且執(zhí)行,執(zhí)行平臺(tái)112包括運(yùn)行環(huán)境113、操作系統(tǒng)111以及使得能夠?qū)崿F(xiàn)運(yùn)行環(huán)境113和操作系統(tǒng)111之間的通信的一個(gè)或多個(gè)應(yīng)用編程接口(API)110。運(yùn)行環(huán)境113包括虛擬機(jī)104,虛擬機(jī)104包括各種組件,諸如存儲(chǔ)器管理器105(其可以包括垃圾收集器)、用于檢查類文件103和方法指令的合法性的驗(yàn)證器106、用于定位和建立類的存儲(chǔ)器中(in-memory)表示的類加載器107、用于執(zhí)行虛擬機(jī)104代碼的解釋器108以及用于產(chǎn)生優(yōu)化的機(jī)器級(jí)別代碼的即時(shí)(JIT)編譯器109。

在實(shí)施例中,計(jì)算架構(gòu)100包括源代碼文件101,源代碼文件101包含以諸如Java、C、C++、C#、Ruby、Perl等之類的特定編程語(yǔ)言編寫的代碼。因此,源代碼文件101遵守用于相關(guān)語(yǔ)言的一組特定的語(yǔ)法和/或語(yǔ)義規(guī)則。例如,以Java編寫的代碼遵守Java語(yǔ)言規(guī)范。然而,由于規(guī)范隨時(shí)間而被更新和修訂,因此源代碼文件101可以與版本號(hào)相關(guān)聯(lián),該版本號(hào)指示源代碼文件101所遵守的規(guī)范的修訂版本。被用于編寫源代碼文件101的確切的編程語(yǔ)言一般不關(guān)鍵。

在各種實(shí)施例中,編譯器102把根據(jù)依照程序員的方便的規(guī)范編寫的源代碼轉(zhuǎn)換成可由特定機(jī)器環(huán)境直接執(zhí)行的機(jī)器代碼或?qū)ο蟠a,或者轉(zhuǎn)換成可由能夠在多種特定機(jī)器環(huán)境上運(yùn)行的虛擬機(jī)104執(zhí)行的中間表示(“虛擬機(jī)代碼/指令”),諸如字節(jié)碼。虛擬機(jī)指令可由虛擬機(jī)104以比源代碼更直接、更高效的方式執(zhí)行。將源代碼轉(zhuǎn)換為虛擬機(jī)指令包括將來自語(yǔ)言的源代碼功能映射到利用諸如數(shù)據(jù)結(jié)構(gòu)之類的底層資源的虛擬機(jī)功能。時(shí)常地,由程序員經(jīng)由源代碼以簡(jiǎn)單術(shù)語(yǔ)呈現(xiàn)的功能被轉(zhuǎn)換成更復(fù)雜的步驟,該更復(fù)雜的步驟更直接地映射到由虛擬機(jī)104駐留在其上的底層硬件支持的指令集。

一般來說,程序要么作為編譯后的程序執(zhí)行,要么作為解釋后的程序執(zhí)行。當(dāng)程序被編譯時(shí),在執(zhí)行之前代碼從第一語(yǔ)言被全局地轉(zhuǎn)變?yōu)榈诙Z(yǔ)言。由于轉(zhuǎn)變代碼的工作是提前執(zhí)行的,因此編譯后的代碼往往具有杰出的運(yùn)行時(shí)性能。另外,由于在執(zhí)行之前所述轉(zhuǎn)變?nèi)值匕l(fā)生,因此可以使用諸如常量折疊、死代碼消除、內(nèi)聯(lián)等之類的技術(shù)來分析和優(yōu)化代碼。然而,取決于正被執(zhí)行的程序,啟動(dòng)時(shí)間可能是顯著的。另外,插入新代碼將會(huì)要求程序離線、重新編譯和重新執(zhí)行。對(duì)于被設(shè)計(jì)為允許在程序的執(zhí)行期間插入代碼的許多動(dòng)態(tài)語(yǔ)言(諸如Java)來說,純編譯的方法一般是不合適的。當(dāng)程序被解釋時(shí),程序的代碼在程序執(zhí)行的同時(shí)被逐行讀取并且轉(zhuǎn)換為機(jī)器級(jí)別的指令。結(jié)果,程序具有短的啟動(dòng)時(shí)間(可以幾乎立刻開始執(zhí)行),但是運(yùn)行中執(zhí)行轉(zhuǎn)換減弱了運(yùn)行時(shí)性能。此外,由于每個(gè)指令被單獨(dú)分析,因此依賴于對(duì)程序的更全局的分析的許多優(yōu)化不能執(zhí)行。

在一些實(shí)施例中,虛擬機(jī)104包括解釋器108和JIT編譯器109(或者實(shí)現(xiàn)這二者的方面的組件),并且使用解釋技術(shù)和編譯技術(shù)的組合來執(zhí)行程序。例如,虛擬機(jī)104最初可以開始于經(jīng)由解釋器108解釋表示程序的虛擬機(jī)指令并同時(shí)追蹤關(guān)于程序行為的統(tǒng)計(jì)數(shù)據(jù),諸如虛擬機(jī)104執(zhí)行不同的代碼部分或代碼塊的頻率。一旦代碼塊超過某一閾值(它是“熱的”),則虛擬機(jī)104調(diào)用JIT編譯器109來執(zhí)行對(duì)塊的分析并且生成替換“熱”代碼塊的經(jīng)優(yōu)化的機(jī)器級(jí)別的指令以供將來執(zhí)行。由于程序往往花費(fèi)其大部分時(shí)間來執(zhí)行它們的整體代碼的小部分,因此僅編譯程序代碼的“熱”部分可以提供與完全編譯的代碼相似的性能,但是沒有啟動(dòng)的損失。此外,盡管優(yōu)化分析局限于被替換的“熱”塊,但是仍然存在與獨(dú)個(gè)地轉(zhuǎn)換每個(gè)指令相比大得多的優(yōu)化潛力。

為了提供清楚的示例,源代碼文件101被示為要由執(zhí)行平臺(tái)111執(zhí)行的程序的“最高級(jí)別”表示。然而,盡管計(jì)算架構(gòu)100將源代碼文件101描繪為“最高級(jí)別”程序表示,但是在其他實(shí)施例中源代碼文件101可以是經(jīng)由“較高級(jí)別”編譯器接收的中間表示,該“較高級(jí)別”編譯器將不同語(yǔ)言的代碼文件處理成源代碼文件101的語(yǔ)言。為了示出清楚的示例,以下公開假設(shè)源代碼文件101遵守基于類的面向?qū)ο蟮木幊陶Z(yǔ)言。然而,這不是利用本文所描述的特征的要求。

在實(shí)施例中,編譯器102接收源代碼文件101作為輸入并且將源代碼文件101轉(zhuǎn)換成虛擬機(jī)104所期望的格式的類文件103。例如,在JVM的背景下,Java虛擬機(jī)規(guī)范的第4章定義了期望類文件103遵守的特定類文件格式。在一些實(shí)施例中,類文件103包含已經(jīng)從源代碼文件101轉(zhuǎn)換而來的虛擬機(jī)指令。然而,在其他實(shí)施例中,類文件103還可以包含其他結(jié)構(gòu),諸如標(biāo)識(shí)關(guān)于各種結(jié)構(gòu)(類、字段、方法等)的常量值和/或元數(shù)據(jù)的表。

以下討論將假設(shè)類文件103中的每個(gè)類文件表示在源代碼文件101中定義的(或者由編譯器102或虛擬機(jī)104動(dòng)態(tài)生成的)各個(gè)“類”。然而,前面提到的假設(shè)不是嚴(yán)格的要求并且將取決于虛擬機(jī)104的實(shí)現(xiàn)方式。因此,不管類文件103的確切格式如何,仍然可以執(zhí)行本文所描述的技術(shù)。在一些實(shí)施例中,類文件103被劃分成一個(gè)或多個(gè)“庫(kù)”或“包”,其中每個(gè)“庫(kù)”或“包”包括提供相關(guān)功能的一批類。例如,一個(gè)庫(kù)可以包含實(shí)現(xiàn)輸入/輸出(I/O)操作、數(shù)學(xué)工具、密碼技術(shù)、圖形實(shí)用程序等的一個(gè)或多個(gè)類文件。此外,一些類(或者這些類內(nèi)的字段/方法)可以包括訪問限制,該訪問限制將其使用限制在特定的類/庫(kù)/包內(nèi)或者限制在具有適當(dāng)許可的類內(nèi)。

2.1示例性類文件結(jié)構(gòu)

圖2示出了根據(jù)實(shí)施例的以框圖形式的關(guān)于類文件200的示例性結(jié)構(gòu)。為了提供清楚的示例,本公開的余下部分假設(shè)計(jì)算架構(gòu)100的類文件103遵守本節(jié)中所描述的示例性類文件200的結(jié)構(gòu)。然而,在實(shí)際環(huán)境中,類文件200的結(jié)構(gòu)將取決于虛擬機(jī)104的實(shí)現(xiàn)方式。此外,本文所討論的一個(gè)或多個(gè)特征可以修改類文件200的結(jié)構(gòu)以例如添加附加結(jié)構(gòu)類型。因此,對(duì)于本文所描述的技術(shù)來說,類文件200的確切結(jié)構(gòu)不是關(guān)鍵的。出于節(jié)2.1的目的,“類”或“該類”是指由類文件200表示的類。

在圖2中,類文件200包括常量表201、字段結(jié)構(gòu)208、類元數(shù)據(jù)204和方法結(jié)構(gòu)209。

在實(shí)施例中,常量表201是除其他功能之外還充當(dāng)類的符號(hào)表的數(shù)據(jù)結(jié)構(gòu)。例如,常量表201可以存儲(chǔ)與源代碼文件101中使用的各種識(shí)別符(諸如類型、范圍、內(nèi)容和/或位置)相關(guān)的數(shù)據(jù)。常量表201具有用于由編譯器102從源代碼文件101導(dǎo)出的值結(jié)構(gòu)202(表示整型、長(zhǎng)整型、雙精度型(double)、浮點(diǎn)型、字節(jié)型、字符串型等類型的常量值)、類信息結(jié)構(gòu)203、名稱和類型信息結(jié)構(gòu)205、字段引用結(jié)構(gòu)206以及方法引用結(jié)構(gòu)207的條目。在實(shí)施例中,常量表201被實(shí)現(xiàn)為將索引i映射到結(jié)構(gòu)j的數(shù)組。然而,常量表201的確切實(shí)現(xiàn)方式不是關(guān)鍵的。

在一些實(shí)施例中,常量表201的條目包括對(duì)其他常量表201條目進(jìn)行索引的結(jié)構(gòu)。例如,用于表示字符串的值結(jié)構(gòu)202之一的條目可以保持將其“類型”標(biāo)識(shí)為字符串的標(biāo)簽以及對(duì)存儲(chǔ)表示該字符串的ASCII字符的字符型、字節(jié)型或整型值的常量表201的一個(gè)或多個(gè)其他值結(jié)構(gòu)202的索引。

在實(shí)施例中,常量表201的字段引用結(jié)構(gòu)206保持對(duì)常量表201中表示定義字段的類的類信息結(jié)構(gòu)203的索引以及對(duì)常量表201中提供字段的名稱和描述符的名稱和類型信息結(jié)構(gòu)205的索引。常量表201的方法引用結(jié)構(gòu)207保持對(duì)常量表201中表示定義方法的類的類信息結(jié)構(gòu)203的索引以及對(duì)常量表201中提供方法的名稱和描述符的名稱和類型信息結(jié)構(gòu)205的索引。類信息結(jié)構(gòu)203保持對(duì)常量表201中保持相關(guān)類的名稱的值結(jié)構(gòu)202的索引。名稱和類型信息結(jié)構(gòu)205保持對(duì)常量表201中存儲(chǔ)字段/方法的名稱的值結(jié)構(gòu)202的索引以及對(duì)常量表201中存儲(chǔ)描述符的值結(jié)構(gòu)202的索引。

在實(shí)施例中,類元數(shù)據(jù)204包括用于類的元數(shù)據(jù),諸如版本號(hào)、常量池中的條目的數(shù)量、字段的數(shù)量、方法的數(shù)量、訪問標(biāo)志(類是否是公有的(public)、私有的(private)、最終的(final)、抽象的(abstract)等)、對(duì)常量表201的類信息結(jié)構(gòu)203中標(biāo)識(shí)該類的一個(gè)類信息結(jié)構(gòu)的索引、對(duì)常量表201的類信息結(jié)構(gòu)203中標(biāo)識(shí)超類(如果有的話)的一個(gè)類信息結(jié)構(gòu)的索引等等。

在實(shí)施例中,字段結(jié)構(gòu)208表示標(biāo)識(shí)類的各個(gè)字段的一組結(jié)構(gòu)。字段結(jié)構(gòu)208針對(duì)類的每個(gè)字段存儲(chǔ)關(guān)于該字段的訪問器標(biāo)志(字段是否是公有的、私有的、最終的、抽象的等)、對(duì)常量表201中保持字段的名稱的值結(jié)構(gòu)202的索引、以及對(duì)常量表201中保持字段的描述符的值結(jié)構(gòu)202的索引。

在實(shí)施例中,方法結(jié)構(gòu)209表示標(biāo)識(shí)類的各個(gè)方法的一組結(jié)構(gòu)。方法結(jié)構(gòu)209針對(duì)類的每個(gè)方法存儲(chǔ)關(guān)于該方法的訪問器標(biāo)志(方法是否是靜態(tài)的、公有的、私有的、同步的等)、對(duì)常量表201中保持方法的名稱的值結(jié)構(gòu)202的索引、對(duì)常量表201中保持方法的描述符的值結(jié)構(gòu)202的索引、以及與如源代碼文件101中定義的方法主體對(duì)應(yīng)的虛擬機(jī)指令。

在實(shí)施例中,描述符表示字段或方法的類型。例如,描述符可以被實(shí)現(xiàn)為遵守特定語(yǔ)法的字符串。盡管確切的語(yǔ)法不是關(guān)鍵的,但是下文描述了幾個(gè)示例。

在描述符表示字段的類型的示例中,描述符標(biāo)識(shí)由字段保持的數(shù)據(jù)的類型。在實(shí)施例中,字段可以保持基本類型、對(duì)象或數(shù)組。當(dāng)字段保持基本類型時(shí),描述符是標(biāo)識(shí)該基本類型的字符串(例如,“B”=byte(字節(jié)型)、“C”=char(字符型)、“D”=double(雙精度型)、“F”=float(浮點(diǎn)型)、“I”=int(整型)、“J”=long int(長(zhǎng)整型)等)。當(dāng)字段保持對(duì)象時(shí),描述符是標(biāo)識(shí)對(duì)象的類名稱的字符串(例如,“L ClassName”)。在該情況中“L”指示引用,因此“L ClassName”表示對(duì)類ClassName的對(duì)象的引用。當(dāng)字段是數(shù)組時(shí),描述符標(biāo)識(shí)由數(shù)組保持的類型。例如,“[B”指示字節(jié)型的數(shù)組,其中“[”指示數(shù)組而“B”指示該數(shù)組保持字節(jié)型的基本類型。然而,由于數(shù)組可以嵌套,因此關(guān)于數(shù)組的描述符還可以指示嵌套。例如,“[[L ClassName”指示數(shù)組,在該數(shù)組中每個(gè)索引保持保持類ClassName的對(duì)象的數(shù)組。在一些實(shí)施例中,ClassName是完全限定的(fully qualified)并且包括類的簡(jiǎn)單名稱以及類的路徑名稱。例如,ClassName可以指示文件存儲(chǔ)在托管類文件200的包、庫(kù)或文件系統(tǒng)中的何處。

在方法的情況中,描述符識(shí)別方法的參量和方法的返回類型。例如,方法描述符可以遵循一般形式“({ParameterDescriptor})ReturnDescriptor”,其中{ParameterDescriptor}是表示參量的字段描述符的列表,而ReturnDescriptor是標(biāo)識(shí)返回類型的字段描述符。例如,字符串“V”可以被用于表示空(void)返回類型。因此,在源代碼文件101中被定義為“Object m(int I,double d,Thread t){…}”的方法匹配描述符“(I D L Thread)L Object”。

在實(shí)施例中,方法結(jié)構(gòu)209中所保持的虛擬機(jī)指令包括引用常量表201的條目的操作。

使用Java作為示例,考慮下面的類:

在上面的示例中,Java方法add12and13被定義在類A中、不帶參數(shù)并且返回整數(shù)。方法add12and13的主體調(diào)用以常量整數(shù)值12和13作為參數(shù)的類B的靜態(tài)方法addTwo,并且返回結(jié)果。因此,在常量表201中,編譯器102除其他條目之外還包括與對(duì)方法B.addTwo的調(diào)用對(duì)應(yīng)的方法引用結(jié)構(gòu)。在Java中,對(duì)方法的調(diào)用向下編譯為JVM的字節(jié)碼中的invoke命令(在該情況中是invokestatic,因?yàn)閍ddTwo是類B的靜態(tài)方法)。invoke命令被提供了對(duì)常量表201中與標(biāo)識(shí)定義addTwo的類“B”的方法引用結(jié)構(gòu)對(duì)應(yīng)的索引、addTwo的名稱“addTwo”以及addTwo的描述符“(I I)I”。例如,假設(shè)前面提到的方法引用被存儲(chǔ)在索引4處,則字節(jié)碼指令可以表現(xiàn)為“invokestatic#4”。

由于常量表201利用承載有標(biāo)識(shí)信息的結(jié)構(gòu)以符號(hào)形式指代類、方法和字段,而不是利用對(duì)存儲(chǔ)器位置的直接引用,因此常量表201的條目被稱為“符號(hào)引用”。符號(hào)引用被用于類文件103的一個(gè)原因是因?yàn)椋涸谝恍?shí)施例中,編譯器102不了解類一旦被加載到運(yùn)行環(huán)境113中將怎樣被存儲(chǔ)以及將被存儲(chǔ)在何處。如將在節(jié)2.3中描述的,在被引用的類(以及相關(guān)結(jié)構(gòu))已經(jīng)被加載到運(yùn)行環(huán)境中并且已經(jīng)被分配了具體的存儲(chǔ)器位置之后,最終,符號(hào)引用的運(yùn)行時(shí)表示由虛擬機(jī)104解析為實(shí)際的存儲(chǔ)器地址。

2.2示例性虛擬機(jī)架構(gòu)

圖3示出了根據(jù)實(shí)施例的以框圖形式的示例性虛擬機(jī)存儲(chǔ)器布局300。為了提供清楚的示例,余下討論將假設(shè)虛擬機(jī)104遵守圖3中描繪的虛擬機(jī)存儲(chǔ)器布局300。另外,盡管虛擬機(jī)存儲(chǔ)器布局300的組成部分可以被稱為存儲(chǔ)器“區(qū)域”,但是不要求存儲(chǔ)器區(qū)域是相鄰的。

在圖3示出的示例中,虛擬機(jī)存儲(chǔ)器布局300被劃分成共享區(qū)域301和線程區(qū)域307。

共享區(qū)域301表示存儲(chǔ)器中在虛擬機(jī)104上執(zhí)行的各個(gè)線程之間共享的結(jié)構(gòu)被存儲(chǔ)的區(qū)域。共享區(qū)域301包括堆302和每個(gè)類的區(qū)域303。在實(shí)施例中,堆302表示從中分配用于類實(shí)例和數(shù)組的存儲(chǔ)器的運(yùn)行時(shí)數(shù)據(jù)區(qū)域。在實(shí)施例中,每個(gè)類的區(qū)域303表示存儲(chǔ)屬于獨(dú)個(gè)類的數(shù)據(jù)的存儲(chǔ)器區(qū)域。在實(shí)施例中,對(duì)于每個(gè)加載的類,每個(gè)類的區(qū)域303包括表示來自類的常量表201的數(shù)據(jù)的運(yùn)行時(shí)常量池304、字段和方法數(shù)據(jù)306(例如,用于保持類的靜態(tài)字段)以及表示用于類的方法的虛擬機(jī)指令的方法代碼305。

線程區(qū)域307表示存儲(chǔ)特定于獨(dú)個(gè)線程的結(jié)構(gòu)的存儲(chǔ)器區(qū)域。在圖3中,線程區(qū)域307包括表示由不同線程利用的每個(gè)線程結(jié)構(gòu)的線程結(jié)構(gòu)308和線程結(jié)構(gòu)311。為了提供清楚的示例,圖3中描繪的線程區(qū)域307假設(shè)兩個(gè)線程正在虛擬機(jī)104上執(zhí)行。然而,在實(shí)際環(huán)境中,虛擬機(jī)104可以執(zhí)行任何任意數(shù)量的線程,其中線程結(jié)構(gòu)的數(shù)量相應(yīng)地縮放。

在實(shí)施例中,線程結(jié)構(gòu)308包括程序計(jì)數(shù)器309和虛擬機(jī)棧310。類似地,線程結(jié)構(gòu)311包括程序計(jì)數(shù)器312和虛擬機(jī)棧313。在實(shí)施例中,程序計(jì)數(shù)器309和程序計(jì)數(shù)器311存儲(chǔ)正由它們各自的線程執(zhí)行的虛擬機(jī)指令的當(dāng)前地址。因此,當(dāng)線程逐句通過(step through)指令時(shí),程序計(jì)數(shù)器被更新以維護(hù)對(duì)當(dāng)前指令的索引。在實(shí)施例中,虛擬機(jī)棧310和虛擬機(jī)棧313各自存儲(chǔ)它們各自的用于保持局部變量和部分結(jié)果的幀(frame),并且還被用于方法調(diào)用和返回。

在實(shí)施例中,幀是用于存儲(chǔ)數(shù)據(jù)和部分結(jié)果、返回用于方法的值以及執(zhí)行動(dòng)態(tài)鏈接的數(shù)據(jù)結(jié)構(gòu)。每次調(diào)用方法時(shí)就創(chuàng)建新幀。當(dāng)使得幀被生成的方法完成時(shí),幀被銷毀。因此,當(dāng)線程執(zhí)行方法調(diào)用時(shí),虛擬機(jī)104生成新幀,并且將該幀推到與線程相關(guān)聯(lián)的虛擬機(jī)棧上。當(dāng)方法調(diào)用完成時(shí),虛擬機(jī)104將方法調(diào)用的結(jié)果傳遞回前一幀并且使當(dāng)前幀出棧。在實(shí)施例中,對(duì)于給定的線程,在任何時(shí)間點(diǎn)處有一個(gè)幀是活動(dòng)的。該活動(dòng)的幀被稱為當(dāng)前幀,使得生成當(dāng)前幀的方法被稱為當(dāng)前方法,而當(dāng)前方法所屬的類被稱為當(dāng)前類。

圖4示出了根據(jù)實(shí)施例的以框圖形式的示例性幀400。為了提供清楚的示例,余下討論將假設(shè)虛擬機(jī)棧310和虛擬機(jī)棧313的幀遵守幀400的結(jié)構(gòu)。

在實(shí)施例中,幀400包括局部變量401、操作數(shù)棧402和運(yùn)行時(shí)常量池引用表403。

在實(shí)施例中,局部變量401被表示為各自保持諸如布爾型、字節(jié)型、字符型、短整型、整型、浮點(diǎn)型、引用型等之類的值的變量的數(shù)組。此外,諸如長(zhǎng)整型或雙精度型之類的一些值類型可以由數(shù)組中的多于一個(gè)條目表示。局部變量401被用于在方法調(diào)用時(shí)傳遞參數(shù)以及存儲(chǔ)部分結(jié)果。例如,當(dāng)響應(yīng)于調(diào)用方法而生成幀400時(shí),參數(shù)可以被存儲(chǔ)在局部變量401內(nèi)的預(yù)定位置中,諸如與調(diào)用中的第一個(gè)到第N個(gè)參數(shù)對(duì)應(yīng)的索引1-N。

在實(shí)施例中,當(dāng)虛擬機(jī)104創(chuàng)建幀400時(shí),操作數(shù)棧402默認(rèn)是空的。然后虛擬機(jī)104供應(yīng)來自當(dāng)前方法的方法代碼305的指令以將來自局部變量501的常量或值加載到操作數(shù)棧502上。其他指令從操作數(shù)棧402取出操作數(shù)、對(duì)它們進(jìn)行操作并且將結(jié)果推到操作數(shù)棧402上。此外,操作數(shù)棧402被用于準(zhǔn)備要被傳遞到方法的參數(shù)以及接收方法結(jié)果。例如,在發(fā)出對(duì)方法的調(diào)用之前,正被調(diào)用的方法的參數(shù)可以被推到操作數(shù)棧402上。然后虛擬機(jī)104生成用于方法調(diào)用的新幀,其中前一幀的操作數(shù)棧402上的操作數(shù)出棧并且被加載到新幀的局部變量401中。當(dāng)被調(diào)用的方法終止時(shí),新幀從虛擬機(jī)棧出棧并且返回值被推回前一幀的操作數(shù)棧402上。

盡管使用諸如“數(shù)組”和/或“?!敝惖臄?shù)據(jù)結(jié)構(gòu)來提及局部變量401和操作數(shù)棧402,但是對(duì)用于實(shí)現(xiàn)這些元素的數(shù)據(jù)結(jié)構(gòu)的類型沒有限制。另外,關(guān)于局部變量401和操作數(shù)棧402在此提及的數(shù)據(jù)結(jié)構(gòu)涉及數(shù)據(jù)結(jié)構(gòu)的高級(jí)別表示。實(shí)施例可以使用各種較低級(jí)別的存儲(chǔ)機(jī)制來實(shí)現(xiàn)這些數(shù)據(jù)結(jié)構(gòu),諸如將局部變量401和/或操作數(shù)棧402的一個(gè)或多個(gè)值存儲(chǔ)在執(zhí)行虛擬機(jī)104的機(jī)器硬件的中央處理單元(CPU)的一個(gè)或多個(gè)寄存器中。較低級(jí)別的指令可以引用對(duì)于較高級(jí)別的指令來說透明的一個(gè)或多個(gè)較低級(jí)別的存儲(chǔ)機(jī)制。盡管可以使用各種較低級(jí)別的存儲(chǔ)機(jī)制(這些較低級(jí)別的存儲(chǔ)機(jī)制都不是由較高級(jí)別的指令指定的)來實(shí)現(xiàn)較高級(jí)別的指令,但是較低級(jí)別的指令引用用于實(shí)現(xiàn)較高級(jí)別的指令的一個(gè)或多個(gè)特定存儲(chǔ)機(jī)制。

在實(shí)施例中,運(yùn)行時(shí)常量池引用表403包含對(duì)當(dāng)前類的運(yùn)行時(shí)常量池304的引用。運(yùn)行時(shí)常量池引用表403被用于支持解析。解析是這樣的過程:通過該過程,常量池304中的符號(hào)引用被翻譯為具體的存儲(chǔ)器地址,按照需要加載類以解析尚未定義的符號(hào)并且將變量訪問翻譯成與這些變量的運(yùn)行時(shí)位置相關(guān)聯(lián)的存儲(chǔ)結(jié)構(gòu)中的合適的偏移。

2.3加載、鏈接和初始化

在實(shí)施例中,虛擬機(jī)104動(dòng)態(tài)地加載、鏈接和初始化類。加載是尋找具有特定名稱的類并且在運(yùn)行環(huán)境113的存儲(chǔ)器內(nèi)創(chuàng)建來自該類的相關(guān)聯(lián)的類文件200的表示的過程。例如,在虛擬機(jī)存儲(chǔ)器布局300的每個(gè)類的區(qū)域303內(nèi)為該類創(chuàng)建運(yùn)行時(shí)常量池304、方法代碼305以及字段和方法數(shù)據(jù)306。鏈接是采用類的存儲(chǔ)器中表示并且將其與虛擬機(jī)104的運(yùn)行時(shí)狀態(tài)組合以使得類的方法可以被執(zhí)行的過程。初始化是執(zhí)行類構(gòu)造函數(shù)以設(shè)置類的字段和方法數(shù)據(jù)306的起始狀態(tài)和/或?yàn)楸怀跏蓟念愒诙?02上創(chuàng)建類實(shí)例的過程。

以下是可以由虛擬機(jī)104實(shí)現(xiàn)的加載、鏈接和初始化技術(shù)的示例。然而,在許多實(shí)施例中步驟可以交錯(cuò),以使得初始類被加載,然后在鏈接期間第二個(gè)類被加載以解析在第一個(gè)類中發(fā)現(xiàn)的符號(hào)引用,這又使得第三個(gè)類被加載,等等。因此,通過加載、鏈接和初始化的階段的進(jìn)程可以根據(jù)類而有所不同。此外,一些實(shí)施例可以延遲(“懶惰地”執(zhí)行)加載、鏈接和初始化過程的一個(gè)或多個(gè)功能直至該類被實(shí)際要求。例如,方法引用的解析可以被延遲直至調(diào)用被引用的方法的虛擬機(jī)指令被執(zhí)行。因此,對(duì)于每個(gè)類何時(shí)執(zhí)行步驟的確切時(shí)機(jī)在實(shí)施方式之間可以差別很大。

為了開始加載過程,虛擬機(jī)104通過調(diào)用加載初始類的類加載器107而啟動(dòng)。用于指定初始類的技術(shù)將隨著實(shí)施例不同而變化。例如,一種技術(shù)可以使虛擬機(jī)104在啟動(dòng)時(shí)接受指定初始類的命令行參數(shù)。

為了加載類,類加載器107解析對(duì)應(yīng)于類的類文件200并且確定類文件200是否為格式良好的(滿足虛擬機(jī)104的語(yǔ)法期待)。如果類文件200不是格式良好的,則類加載器107生成錯(cuò)誤。例如,在Java中,可能以異常的形式生成錯(cuò)誤,該異常被拋給異常處理器以供處理。否則,類加載器107通過在每個(gè)類的區(qū)域303內(nèi)分配用于該類的運(yùn)行時(shí)常量池304、方法代碼305以及字段和方法數(shù)據(jù)306來生成該類的存儲(chǔ)器中表示。

在一些實(shí)施例中,當(dāng)類加載器107加載類時(shí),類加載器107還遞歸加載被加載的類的超類。例如,虛擬機(jī)104可以確保:在進(jìn)行對(duì)于特定類的加載、鏈接和初始化過程之前,該特定類的超類被加載、鏈接和/或初始化。

在鏈接期間,虛擬機(jī)104驗(yàn)證類、準(zhǔn)備類并且執(zhí)行類的在運(yùn)行時(shí)常量池304中定義的符號(hào)引用的解析。

為了驗(yàn)證類,虛擬機(jī)104檢查類的存儲(chǔ)器中表示在結(jié)構(gòu)上是否是正確的。例如,虛擬機(jī)104可以檢查除了泛型類對(duì)象之外的每個(gè)類具有超類、檢查最終類不具有子類以及最終方法沒有被重載、檢查當(dāng)前類是否具有對(duì)于常量池304中所引用的類/字段/結(jié)構(gòu)的正確的訪問許可、檢查方法的虛擬機(jī)104代碼將不會(huì)引發(fā)意外行為(例如,確保跳轉(zhuǎn)指令不會(huì)使虛擬機(jī)104超出方法的末尾),等等。在驗(yàn)證期間執(zhí)行的確切檢查取決于虛擬機(jī)104的實(shí)現(xiàn)方式。在一些情況中,驗(yàn)證可以導(dǎo)致附加的類被加載,但是在繼續(xù)進(jìn)行之前不一定要求這些類還被鏈接。例如,假設(shè)類A包含對(duì)類B的靜態(tài)字段的引用。在驗(yàn)證期間,虛擬機(jī)104可以檢查類B以確保所引用的靜態(tài)字段實(shí)際存在,這可能導(dǎo)致類B的加載,但不一定導(dǎo)致類B的鏈接或初始化。然而,在一些實(shí)施例中,某些驗(yàn)證檢查可以被推遲至較晚的階段,諸如在符號(hào)引用的解析期間被檢查。例如,一些實(shí)施例可以推遲檢查對(duì)于符號(hào)引用的訪問許可直至這些引用被解析。

為了準(zhǔn)備類,虛擬機(jī)104將位于該類的字段和方法數(shù)據(jù)306內(nèi)的靜態(tài)字段初始化為默認(rèn)值。在一些情況中,將靜態(tài)字段設(shè)置為默認(rèn)值可以與運(yùn)行該類的構(gòu)造函數(shù)不同。例如,驗(yàn)證過程可以在初始化期間將靜態(tài)字段清零或者將靜態(tài)字段設(shè)置為構(gòu)造函數(shù)希望這些字段具有的值。

在解析期間,虛擬機(jī)104根據(jù)類的運(yùn)行時(shí)常量池304中所包括的符號(hào)引用來動(dòng)態(tài)地確定具體的存儲(chǔ)器地址。為了解析符號(hào)引用,虛擬機(jī)104利用類加載器107來加載符號(hào)引用中識(shí)別的類(如果還未加載)。一旦該類被加載,則虛擬機(jī)104了解所引用的類及其字段/方法的每個(gè)類的區(qū)域303內(nèi)的存儲(chǔ)器位置。然后虛擬機(jī)104將符號(hào)引用替換為對(duì)所引用的類、字段或方法的具體的存儲(chǔ)器位置的引用。在實(shí)施例中,虛擬機(jī)104高速緩存解析以便在當(dāng)虛擬機(jī)104處理另一個(gè)類時(shí)遇到相同的類/名稱/描述符的情況下重新使用。例如,在一些情況中,類A和類B可以調(diào)用類C的同一方法。因此,當(dāng)針對(duì)類A執(zhí)行解析時(shí),該結(jié)果可以被高速緩存并且在類B中的相同符號(hào)引用的解析期間被重新使用以降低開銷。

在一些實(shí)施例中,在鏈接期間解析符號(hào)引用的步驟是可選的。例如,實(shí)施例可以以“懶惰的”方式執(zhí)行符號(hào)解析,從而延遲解析的步驟直至需要所引用的類/方法/字段的虛擬機(jī)指令被執(zhí)行。

在初始化期間,虛擬機(jī)104執(zhí)行類的構(gòu)造函數(shù)以設(shè)置該類的起始狀態(tài)。例如,初始化可以初始化類的字段和方法數(shù)據(jù)306以及在由構(gòu)造函數(shù)創(chuàng)建的堆302上生成/初始化任何類實(shí)例。例如,用于類的類文件200可以指定特定方法是用于設(shè)立起始狀態(tài)的構(gòu)造函數(shù)。因此,在初始化期間,虛擬機(jī)104執(zhí)行該構(gòu)造函數(shù)的指令。

在一些實(shí)施例中,虛擬機(jī)104通過最初檢查字段/方法在所引用的類中是否被定義來執(zhí)行對(duì)字段和方法引用的解析。否則,虛擬機(jī)104針對(duì)所引用的方法/字段遞歸搜索所引用的類的超類直至字段/方法被定位或到達(dá)最高級(jí)別的超類,在到達(dá)最高級(jí)別的超類的情況下生成錯(cuò)誤。

3.0值類型概述

在一些實(shí)施例中,虛擬機(jī)104提供許多不同的方式來創(chuàng)建聚合類型。例如,虛擬機(jī)104可以提供具有標(biāo)識(shí)的異構(gòu)聚合(例如,經(jīng)由“類”)和具有標(biāo)識(shí)的同構(gòu)聚合(例如,經(jīng)由“數(shù)組”)。值類型表示異構(gòu)的并且沒有標(biāo)識(shí)的另一類聚合。因此,類似于原生類型(諸如字節(jié)型、短整型、整型、長(zhǎng)整型、浮點(diǎn)型、雙精度型、字符型和布爾型),如果兩個(gè)存儲(chǔ)器區(qū)域包含相同的值類型,則這些存儲(chǔ)器區(qū)域中的數(shù)據(jù)不能被區(qū)分。這與在一些實(shí)施例中各自包含具有諸如對(duì)象的存儲(chǔ)器地址之類的唯一標(biāo)識(shí)號(hào)的頭部信息的類對(duì)象相反。對(duì)象標(biāo)識(shí)具有占用空間和性能成本,這是與許多其他面向?qū)ο蟮恼Z(yǔ)言不同,Java具有原生類型的主要原因。這些成本對(duì)于不具有許多字段來分?jǐn)傤~外成本的小對(duì)象來說是非常難以負(fù)擔(dān)的。

在一些實(shí)施例中,在占用空間方面,具有標(biāo)識(shí)的對(duì)象被分配在堆302上、具有一個(gè)或多個(gè)字的對(duì)象頭部并且(除非死亡,否則)具有指向它們的一個(gè)或多個(gè)指針。在性能方面,每個(gè)相異的實(shí)例可以被分配在堆302上并且即使對(duì)象僅包含單個(gè)字段(例如,java.lang.Integer),每個(gè)訪問也包括相關(guān)的加載(指針遍歷)以到達(dá)“載荷”。另外,在Java中,對(duì)象頭部支持包括Object.getClass、Object.wait和System.identityHashCode的許多基于標(biāo)識(shí)的操作。

對(duì)象標(biāo)識(shí)用來支持可變性,其中對(duì)象的狀態(tài)可以是可變的,但是維持相同的內(nèi)部對(duì)象。例如,對(duì)象的字段可以被修改,但是盡管字段的值發(fā)生改變,頭部信息仍然將對(duì)象識(shí)別為“相同的”。另外,在一些實(shí)施例中,對(duì)象標(biāo)識(shí)還用來支持多態(tài)性。然而,許多編程慣用語(yǔ)法(idiom)不要求標(biāo)識(shí),并且由于不付出存儲(chǔ)器占用空間、局部性和標(biāo)識(shí)的優(yōu)化懲罰而受益。盡管有重大的嘗試,但是許多虛擬機(jī)在解決標(biāo)識(shí)對(duì)于程序是否有意義方面仍然較差,并且因此可能悲觀地對(duì)于不需要標(biāo)識(shí)的許多對(duì)象支持標(biāo)識(shí)。

在一些實(shí)施方式中,甚至名義上無狀態(tài)的(具有所有最終字段的)對(duì)象可以即使在高度優(yōu)化的代碼中使其標(biāo)識(shí)隨時(shí)被追蹤,以免對(duì)象被用作同步的手段或者由依賴于標(biāo)識(shí)的任何其他機(jī)制使用。該內(nèi)在的“有狀態(tài)性”妨礙許多優(yōu)化。在一些情況中,逃逸分析(escape analysis)技術(shù)有時(shí)可以減輕這些成本,但是這些技術(shù)在代碼復(fù)雜性面前是脆弱的并且在分開編譯的情況下幾乎完全失效。

運(yùn)行示例:Point(點(diǎn))

考慮Point類:

即使Point是不可變的,虛擬機(jī)104也不一定知道Point對(duì)象的標(biāo)識(shí)將從來不被使用(例如,出于同步的目的將對(duì)象用作內(nèi)部鎖)。結(jié)果,Point被表示為關(guān)于x和y的“箱”對(duì)象。在一種實(shí)現(xiàn)方式中,Point對(duì)象的數(shù)組包括額外的對(duì)象頭部(8到16字節(jié))和引用(4到8字節(jié)),從而意味著這些8字節(jié)的數(shù)據(jù)(用于x和y整型)占用20到32字節(jié)的堆空間,而迭代該數(shù)組意味著對(duì)于所訪問的每個(gè)Point對(duì)象的指針解引用。這破壞了數(shù)組的內(nèi)在局部性并且限制了程序性能(更不用說分配帶來了垃圾收集器的工作)。程序員通常借助于如將點(diǎn)數(shù)組表示為兩個(gè)整型數(shù)組的技巧來避免這些成本,但是這犧牲了封裝性(和可維護(hù)性)只是為了補(bǔ)回標(biāo)識(shí)的性能損失。另一方面,如果Point可以用與諸如整型之類的原生類型相同的方式表示,則虛擬機(jī)104可以在寄存器中存儲(chǔ)Point、將它們推到棧上、遍歷具有局部性的數(shù)組以及使用少得多的存儲(chǔ)器,而不損失封裝性。

在實(shí)施例中,值類型表示沒有標(biāo)識(shí)的由用戶定義的聚合類型,其可以以源代碼文件101和虛擬機(jī)104的指令集的語(yǔ)言中顯現(xiàn),從而在不犧牲封裝性的情況下支持存儲(chǔ)器高效的和局部性高效的編程慣用語(yǔ)法。在實(shí)施例中,值類型是可以包含原生類型、引用類型或者甚至其他值類型的異構(gòu)聚合。

在一些實(shí)施例中,例如在Java中,用于類的許多定義和封裝機(jī)構(gòu)可以被用于容易且安全地建立基于新的值類型結(jié)構(gòu)體的數(shù)據(jù)結(jié)構(gòu)。例如,值類型可以被當(dāng)作特殊標(biāo)記的并且受限的類定義的形式。然而,同時(shí),值類型對(duì)于虛擬機(jī)104的用戶來說(在語(yǔ)義的意義上)僅僅充當(dāng)新型的原生。

如將在下面的節(jié)中探索的,盡管值類型有用地類似于類,但是(像原生那樣)在值類型和引用類型之間做出清楚且系統(tǒng)的區(qū)分是有用的。因此,在一些實(shí)施例中,新的指令被添加到虛擬機(jī)104的指令集以創(chuàng)建、發(fā)布和/或修改值類型。然而,在其他實(shí)施例中,當(dāng)前指令被重載,以便根據(jù)指令是否對(duì)引用、原生類型和/或值類型操作而執(zhí)行不同的功能。

3.1用例

在實(shí)施例中,值類型可以被引入到虛擬機(jī)104以支持許多特征,這些特征在使用基于標(biāo)識(shí)的聚合的情況下可能不存在或者是以次優(yōu)方式實(shí)現(xiàn)的。然而,使用值類型可以高效地實(shí)現(xiàn)以下示例。一些示例包括:

數(shù)值(numeric)。諸如JVM之類的一些虛擬機(jī)僅提供有限數(shù)量的高效數(shù)值類型;如果使用這些數(shù)值類型不能高效地解決問題,則必須替代地使用具有標(biāo)識(shí)的聚合(以及相關(guān)聯(lián)的開銷)。比如復(fù)數(shù)、擴(kuò)展精度的整數(shù)或無符號(hào)整數(shù)以及十進(jìn)制(decimal)類型之類的數(shù)值類型是廣泛有用的,但是僅可以由原生和/或?qū)ο箢悂斫?有損于類型安全性、封裝性和/或性能)。

本地類型(native type)?,F(xiàn)代處理器支持各種各樣的本地?cái)?shù)據(jù)類型,并且(像數(shù)值那樣)它們中的僅僅一些被直接映射為虛擬機(jī)所支持的原生。這使得編寫直接編譯為諸如向量指令之類的包含本地類型的指令的代碼是困難的或者不可能的。

代數(shù)數(shù)據(jù)類型。使用對(duì)象箱可以實(shí)現(xiàn)像Optional<T>或Choice<T,U>那樣的數(shù)據(jù)類型。然而,就小的無標(biāo)識(shí)的聚合而言,許多這樣的類型(尤其是像元組那樣的產(chǎn)品類型)具有自然的表示。單元類型(空類似物(void-like)和度量二者)對(duì)于表示代數(shù)數(shù)據(jù)類型有時(shí)也是有用的,但前提是它們的占用空間開銷可以被顯著降低或被驅(qū)使為零。

元組。值的元素可以自身被當(dāng)作值并且不一定需要對(duì)象箱。

游標(biāo)(cursor)。迭代器或其他游標(biāo)在復(fù)制數(shù)據(jù)結(jié)構(gòu)中并且不一定需要對(duì)象箱。此外,(所管理的和/或本地的)數(shù)據(jù)結(jié)構(gòu)的客戶機(jī)可以在保持完整封裝性和類型安全性的情況下繞過數(shù)據(jù)結(jié)構(gòu)中的迭代器和其他“智能指針”。

3.2示例性值類型特性

在一些實(shí)施例中,在虛擬機(jī)104級(jí)別處的值類型設(shè)施提供以下有益特性中的一個(gè)或多個(gè):

標(biāo)量化。在一些實(shí)施例中,值類型的實(shí)例可以被定期分解為它們的成分并且存儲(chǔ)在寄存器或者棧(諸如虛擬機(jī)棧310)中,而不是在堆302上。當(dāng)作為包含對(duì)象的部分被存儲(chǔ)在堆302中時(shí),虛擬機(jī)104可自由地使用值類型的扁平化的、無指針的表示。

包裝(wrapping)。在一些實(shí)施例中,值類型具有拆箱表示和裝箱表示這二者。拆箱表示在可行的情況下被使用以降低開銷;裝箱表示被用于與需要引用類型的API的互操作性。與例如Java中現(xiàn)有的原生包裝器不同,裝箱表示可以從值類型的描述自動(dòng)生成。例如,每個(gè)值類型可以使用類文件來定義,并且虛擬機(jī)104使用該類文件來自動(dòng)生成表示用于值類型的箱對(duì)象的新的類文件。作為另一示例,源代碼文件101中定義的值類型由編譯器102編譯為用于值類型的分開的類文件和值類型的裝箱形式。作為又一示例,值類型和值類型的裝箱形式這二者可以共享同一類文件,但是虛擬機(jī)將取決于上下文以不同方式對(duì)待值類型的使用。

行為。在一些實(shí)施例中,值類型不僅僅是數(shù)據(jù)的元組;它們還可以以方法的形式定義行為。例如,復(fù)數(shù)值類型的定義可以定義用于執(zhí)行復(fù)數(shù)運(yùn)算的方法。然后如果硬件原生是可用的(比如對(duì)于128位的數(shù)值),則虛擬機(jī)104可以選擇內(nèi)部化該行為。類似地,數(shù)據(jù)結(jié)構(gòu)游標(biāo)可以定義工廠方法和訪問方法,同時(shí)保持其成分值被安全地封裝。諸如Java中的toString和equals之類的實(shí)用程序方法(utility method)可以被強(qiáng)加于值類,但不一定如此。在一些實(shí)施例中,實(shí)用程序方法能夠逐個(gè)值類型地定制。

名稱。諸如JVM類型系統(tǒng)之類的一些類型系統(tǒng)幾乎全部是標(biāo)稱的(nominal),而不是結(jié)構(gòu)的。類似地,在一些實(shí)施例中,值類型的成分可以通過名稱識(shí)別,而不是僅通過元素號(hào)識(shí)別。(這使得值類型更像記錄而不是元組)。

互操作性。在諸如JVM之類的一些虛擬機(jī)中,存在針對(duì)具有值對(duì)應(yīng)物的泛型對(duì)象的若干操作,諸如equals、hashCode和toString。在一些實(shí)施例中,虛擬機(jī)(在缺乏來自值類型的作者的指令的情況下)按成分實(shí)現(xiàn)這些方法。除了對(duì)象(Object)之外,諸如Comparable(可比較型)之類的其他類型還可以與合適的值類型互操作,從而向諸如TreeSet<UnsignedInteger>之類的類型打開大門。

封裝性。在一些實(shí)施例中,值類型具有私有成分,正如對(duì)象具有私有字段。這使得例如安全的外部(foreign)“指針”或游標(biāo)成為可能。值類型可以被配置為阻止?jié)撛诘墓粽咄ㄟ^提取私有成分或通過合法操作的勉強(qiáng)組合造出非法值來摧毀封裝性。

可驗(yàn)證性。在一些實(shí)施例中,虛擬機(jī)104的指令集中的對(duì)于值類型的支持是能夠被驗(yàn)證器106驗(yàn)證的。

變量。在一些實(shí)施例中,諸如字段、數(shù)組元素、局部變量和方法參數(shù)之類的變量類型都被配置為保持值類型。此外,方法被配置為返回值類型。此外,修飾符(諸如Java中的final和volatile)可以被應(yīng)用于值類型以實(shí)現(xiàn)它們的常規(guī)效果。

數(shù)組。在一些實(shí)施例中,值類型的數(shù)組被打包(packed),非間接地、類似于原生的數(shù)組。這不一定意味著數(shù)組本身被打包在其他對(duì)象內(nèi)部。因此,數(shù)組可以保持值類型元素的扁平化表示,但是如果數(shù)組是對(duì)象的字段,則對(duì)象可以存儲(chǔ)可被分配在堆302上的數(shù)組的指針。

扁平化。值類型提供了用于表達(dá)具有較少指針間接的數(shù)據(jù)結(jié)構(gòu)的自然方式。因此,使用值類型來使數(shù)據(jù)扁平化允許虛擬機(jī)104更高效地布置一些數(shù)據(jù)結(jié)構(gòu)。

3.3示例性限制

由于值類型不具有標(biāo)識(shí),因此存在某些操作,一些實(shí)施例可以選擇不允許對(duì)值類型進(jìn)行這些操作或者為這些操作分配新的含義以供在值類型的背景下使用。在一些實(shí)施例中,對(duì)值類型的限制在虛擬機(jī)104中被實(shí)現(xiàn)為供驗(yàn)證器106遵循的附加規(guī)則。因此,如果類內(nèi)的方法包含違背規(guī)則的代碼,則生成異?;蝈e(cuò)誤。以下是一些示例:

鎖定。為了支持諸如在Java語(yǔ)言中執(zhí)行的同步,對(duì)象有時(shí)被用作經(jīng)同步的語(yǔ)句的鎖對(duì)象。在一些實(shí)施例中,由于缺乏對(duì)于該特征所期待的頭部信息,因此虛擬機(jī)104不允許針對(duì)這些語(yǔ)句使用值類型。此外,在一些實(shí)施例中,虛擬機(jī)104不允許針對(duì)值類型調(diào)用與同步相關(guān)的方法。例如,Java中的wait(等待)和notify(通知)方法。

標(biāo)識(shí)比較。(在Java中)針對(duì)對(duì)象的“==”操作符執(zhí)行標(biāo)識(shí)比較,但是針對(duì)原生,該操作符執(zhí)行按位比較。由于值類型不一定具有指針,因此該操作符不適用于值類型。在一些實(shí)施例中,通過遞歸地執(zhí)行“==”操作(最終基于較低級(jí)別的對(duì)象/原生來評(píng)估)、調(diào)用equals方法和/或執(zhí)行按位比較來執(zhí)行解釋針對(duì)值類型的諸如“==”之類的操作符。

標(biāo)識(shí)散列碼。諸如經(jīng)由Java中的System.identityHashCode之類的用于對(duì)象的基于標(biāo)識(shí)的散列碼不適用于值類型。做出對(duì)象的基于標(biāo)識(shí)的區(qū)分的、像序列化那樣的內(nèi)部操作要么不適用于值類型(由于它們不適用于原生),要么會(huì)使用由值類型定義的單獨(dú)的散列碼方法供應(yīng)的基于值的區(qū)分。例如,按成分的散列計(jì)算可以被還原為默認(rèn)。然而,當(dāng)值類型的成分是私有的時(shí),這可能泄露可被攻擊使用的信息。

克隆。在一些實(shí)施例中,虛擬機(jī)104將諸如Java中的Clone方法之類的克隆解釋為對(duì)于值類型的標(biāo)識(shí)轉(zhuǎn)變。

終止化(finalization)。在一些實(shí)施例中,對(duì)于值類型的終止化是不允許的,因此在許多實(shí)施例中對(duì)值類型的終止化將沒有用處(但是值類型可以保持自身可終止化的引用類型的成分)。

以上限制中的許多限制對(duì)應(yīng)于Java中針對(duì)所謂的基于值的類的限制。實(shí)際上,在實(shí)施例中,每個(gè)值類型的裝箱形式是基于值的類。

在一些實(shí)施例中,虛擬機(jī)104對(duì)值類型做出“軟”限制以確保值類型在存儲(chǔ)空間和/或成分?jǐn)?shù)量方面不會(huì)“太大”。由于值類型通過值來傳遞,因此隨著成分?jǐn)?shù)量增加,復(fù)制許多成分的開銷越來越可能壓倒通過移除指針和對(duì)象頭部的開銷而獲得的任何節(jié)省。由于類對(duì)象是使用指針通過引用來傳遞,因此大組的成分值可以可替代地使用類來建模。

在一些實(shí)施例中,值類型的精心構(gòu)思的使用通過省略對(duì)象指針和頭部以及定期通過值傳遞成分來獲得性能和復(fù)雜度的益處。具有少量成分的值類型通常整齊地匹配大多數(shù)當(dāng)前的中央處理單元(CPU)(其對(duì)寄存器文件的尺寸具有相對(duì)較小的限制)的能力。當(dāng)超過這些限制時(shí),一些實(shí)施例中的虛擬機(jī)104具有將值類型分散到棧(諸如虛擬機(jī)棧310/313)和/或所管理的堆302存儲(chǔ)器上的靈活性。

在一些實(shí)施例中,取決于值類型的尺寸和/或值類型是否在不能被修改的容器中,虛擬機(jī)104在通過值傳遞值類型或通過引用傳遞值類型之間切換。在后面的節(jié)中以更多細(xì)節(jié)探索該特征。

3.4指針管理

當(dāng)使用值類型的扁平化表示時(shí),值類型不被指針訪問或者這種指針在虛擬機(jī)104實(shí)現(xiàn)內(nèi)對(duì)用戶隱藏。因此,即使虛擬機(jī)104在底層使用指針,虛擬機(jī)104也確保從用戶的視角來看值類型遵循通過值傳遞的行為。在一些實(shí)施例中,某些附加操作也是虛擬機(jī)104不允許的或者被虛擬機(jī)104分配新的含義。

空值(null)??罩凳敲總€(gè)引用類型的有效值,其意味著“沒有實(shí)例”。然而,在值類型的背景下,空值可能是不適用的,這與在大多數(shù)語(yǔ)言中空值通常不適用于原生大致相同。因此,在一些實(shí)施例中,對(duì)于值類型來說被指派為空值以及與空值相比較是不允許的。然而,該限制將不適用于值類型的裝箱形式,其中將值類型裝箱的容器對(duì)象可以保持空值并且可以與空值相比較。

副作用。盡管包含整個(gè)值的變量可以被重新指派為不同的值,但是值的單獨(dú)部分通常不受到分段的副作用的影響,就好像它們通過對(duì)于該值的指針被訪問一樣。因此,整數(shù)可以從2被更新到3,但是在一些實(shí)施例中用戶被限制為整個(gè)值指派。結(jié)果,不向用戶提供可以改變2的最低位以將該值改變?yōu)?的代碼指令。諸如Java之類的某些語(yǔ)言在該方向上給出的是像intval|=1一樣的復(fù)合指派操作。此外,在第一變量處將值從2改變?yōu)?不會(huì)導(dǎo)致其他地方的第二變量變成3(當(dāng)兩個(gè)變量都指向值被改變的同一存儲(chǔ)器位置時(shí)會(huì)出現(xiàn)此情況)。結(jié)果,在一些實(shí)施例中,(從用戶的角度來看)虛擬機(jī)104阻止了分段的副作用。然而,盡管從用戶的視角來看,值類型看上去是作為整體被替換(作為不可變性的性質(zhì))并且不會(huì)導(dǎo)致對(duì)于其他變量的副作用(作為扁平性的性質(zhì)),但是在一些實(shí)施例中在底層虛擬機(jī)104可以執(zhí)行違背該性質(zhì)的優(yōu)化。例如,盡管在語(yǔ)義上代碼表現(xiàn)的就像Point A被Point B完整地替換一樣,但是在底層,虛擬機(jī)104可以僅替換不同的成分以作為優(yōu)化的形式。作為另一示例,假如在語(yǔ)義上虛擬機(jī)104諸如通過僅在值類型不能改變的(例如,值類型是最終的)情況下執(zhí)行該優(yōu)化來阻止副作用,則在值類型較大的情況中,指針可以被用于最小化復(fù)制開銷。

在一些實(shí)施例中,語(yǔ)言允許通過指針訪問值類型,多達(dá)并且包括成分變化。在這種實(shí)施例中,該概念的復(fù)雜度協(xié)助本地?cái)?shù)據(jù)結(jié)構(gòu)以及虛擬機(jī)104數(shù)據(jù)。

引用轉(zhuǎn)換。在一些實(shí)施例中,像原生類型那樣,值類型可以被裝箱以便被用作引用。因此,在一些實(shí)施例中,虛擬機(jī)104具有用于隱式地對(duì)值類型進(jìn)行裝箱和拆箱的規(guī)則,類似于Java當(dāng)前怎樣執(zhí)行用于原生值的裝箱和拆箱。例如,通過基于上下文在整型和相應(yīng)的Integer(整數(shù))值類之間自動(dòng)轉(zhuǎn)換。

指針多態(tài)性。在一些實(shí)施例中,對(duì)象并入運(yùn)行時(shí)類型信息,方法可以是虛擬的,類型可以在運(yùn)行時(shí)被測(cè)試,以及(許多)靜態(tài)引用類型可以在運(yùn)行時(shí)指向一系列具體的子類。在這種實(shí)施例中,由于指針變量盡管具有固定的尺寸但是可以指代任何尺寸和類型的數(shù)據(jù),因此前面提到的特征起作用。由于值類型沒有頭部來承載類型信息并且被設(shè)計(jì)為被扁平化到它們的包含對(duì)象中,因此值類型(在一些實(shí)施例中)不能被動(dòng)態(tài)地類型測(cè)試并且不能具有可變的尺寸。結(jié)果,在一些實(shí)施例中,虛擬機(jī)104阻止子類化(sub-classing),因?yàn)樵撎卣鲗?duì)于值類型沒什么用處。然而,諸如Java中的Comparable接口之類的抽象的超類和接口仍然可以被使用,因?yàn)檫@些結(jié)構(gòu)體不能被分開實(shí)例化。在一些實(shí)施例中,值類型實(shí)現(xiàn)頭部信息的縮減集合,而不是沒有頭部信息,諸如包括尺寸數(shù)據(jù)以支持可變尺寸,但是不包括用于實(shí)現(xiàn)標(biāo)識(shí)特征的諸如標(biāo)識(shí)號(hào)(例如,對(duì)象的存儲(chǔ)器地址)之類的其他信息。

反射(reflection)。作為指針多態(tài)性的極端情況,在諸如Java之類的語(yǔ)言中,任何對(duì)象可以被轉(zhuǎn)換為頂級(jí)類型Object并且可以針對(duì)它的字符串表示、它的類、它的字段和字段值的集合等等而被檢查。由于在一些實(shí)施例中值類型不支持超類,因此虛擬機(jī)104可以禁用轉(zhuǎn)換值類型并且因此還禁用反射。然而,在一些實(shí)施例中,值類型的方法可以包括創(chuàng)建與從Object類型生成的字符串表示類似的字符串表示的方法。

原子性。指針提供了到其對(duì)象(可以原子地改變)的訪問路徑。因此,競(jìng)爭(zhēng)的線程觀察到舊對(duì)象或新對(duì)象,而不是二者的混合。相比之下,多字段值可能經(jīng)受數(shù)據(jù)競(jìng)爭(zhēng)的,在數(shù)據(jù)競(jìng)爭(zhēng)中競(jìng)爭(zhēng)的線程可能觀察到新字段值和舊字段值的混合。在當(dāng)前的語(yǔ)言中,在長(zhǎng)整型和雙精度型類型的情況下該“結(jié)構(gòu)撕裂”問題有時(shí)可以作為極端情況被觀察到,但是在值類型的情況下該問題更加急迫,因?yàn)樗梢試?yán)重地?fù)p害封裝性。在一些實(shí)施例中,虛擬機(jī)104在類型使用位置和類型定義位置這二者處按照請(qǐng)求供應(yīng)原子性。這類似于諸如Java之類的語(yǔ)言在在長(zhǎng)整型和雙精度型變量被聲明為易變的情況下如何在類型使用站點(diǎn)處按照請(qǐng)求供應(yīng)原子性。在當(dāng)前硬件中保證原子性的成本足夠大以致于對(duì)于不要求原子性或僅要求某些變量具有原子性的程序,始終要求原子性可能導(dǎo)致大量不必要的開銷。精確的折衷跨平臺(tái)變化。

3.5示例性定義

在一些實(shí)施例中,值類型的一些特性是類常見的:一批經(jīng)命名的、類型成分(字段)、行為(方法)、隱私(訪問控制)、編程初始化(構(gòu)造器)等。因此,在一些實(shí)施例中,使用特殊標(biāo)記的類文件來定義值類型。然而,虛擬機(jī)104可以經(jīng)由驗(yàn)證器106對(duì)這些類文件施加特殊的規(guī)則,諸如在先前的節(jié)中所描述的限制。類似地,用于值類型的語(yǔ)法元素可以被精心設(shè)計(jì)以便看上去類似于源語(yǔ)言中的寫類。

在諸如Java之類的一些語(yǔ)言中,存在采取該方法的先例,諸如使用類文件103來表示接口,因?yàn)檫@些接口還與普通類有相似之處。除了模式位和小語(yǔ)法的附加之外,在一些實(shí)施例中,接口的二進(jìn)制可以與適當(dāng)?shù)念惖亩M(jìn)制相同,除了接口具有附加的語(yǔ)法和語(yǔ)義限制。類似地,值類型可以在源代碼文件101中定義并且使用語(yǔ)法的小改變來寫,但是具有由驗(yàn)證器106應(yīng)用于所得到的類文件103的附加限制。

通過使用示例性語(yǔ)法,之前提供的Point示例可以被重寫為如下的值類型:

上面的示例和引用等價(jià)物之間的語(yǔ)法區(qū)別從將結(jié)構(gòu)體標(biāo)記為值類型而不是適當(dāng)?shù)念惖年P(guān)鍵字_ByValue開始。然而,這僅是示例性的語(yǔ)法,將結(jié)構(gòu)體標(biāo)記為值類型的任何方式是容許的,諸如通過關(guān)鍵字、符號(hào)或任何其他語(yǔ)法來標(biāo)記。此外,諸如字段、結(jié)構(gòu)體和/或方法之類的用于源語(yǔ)言的相同的編碼慣用語(yǔ)法可以被重復(fù)使用以將這些值/行為添加到值類型的定義。在一些實(shí)施例中,如果用戶在源代碼文件101中未提供實(shí)用程序方法(并且語(yǔ)言允許該省略),虛擬機(jī)104或編譯器102填補(bǔ)某些實(shí)用方法(諸如按成分的hashCode、equals或toString)。

如果另一個(gè)類聲明類型Point的字段,則虛擬機(jī)104將分配用于在托管對(duì)象中的x和y成分的存儲(chǔ),而不是對(duì)Point箱的引用。這可以被視為對(duì)象內(nèi)聯(lián)或扁平化。類似地,Point的數(shù)組將被布局為交替的x和y值的經(jīng)打包的數(shù)組,而不是對(duì)存儲(chǔ)x和y值對(duì)的容器的一系列引用。

在一些實(shí)施例中,由于與類相似地使用特征和語(yǔ)法來向用戶暴露值類型,因此值類型的定義對(duì)于源語(yǔ)言的程序員來說立刻是清楚的。然而,在各種實(shí)施例中不適用于值類型的一些熟悉的特征(諸如Java中的extends或protected)可能是不適用的。因此,如果用戶嘗試在值類型的定義中包括這些屬性,則虛擬機(jī)104的編譯器102或驗(yàn)證器106拋出異?;蛏慑e(cuò)誤。

在一些實(shí)施例中,源語(yǔ)言已經(jīng)具有表達(dá)限制的關(guān)鍵字或其他機(jī)制,諸如子字段在構(gòu)造之后的不可變性。例如,Java中的final關(guān)鍵字。因此,如果用戶不再使用final關(guān)鍵字,則編譯器102可以提供解釋該關(guān)鍵字必需的錯(cuò)誤或者隱式地將關(guān)鍵字添加到所生成的類文件。此外,在一些實(shí)施例中,如果final屬性丟失,則虛擬機(jī)104隱式地將final屬性添加到所生成的類文件,或者將該屬性當(dāng)作已經(jīng)被設(shè)置。

3.6示例性用法

前一節(jié)描述了值類型可以如何以與類相同的方式編碼,因此下一個(gè)問題是在虛擬機(jī)104中如何定義行為以提供好像值類型是原生那樣的對(duì)待。下面是Point類的一些示例性使用:

在這些示例中,Point可以是字段、參數(shù)、局部變量或者返回值。在所有這些情況中,在一些實(shí)施例中虛擬機(jī)104將Point的成分放置在獨(dú)立地管理的位置中,諸如機(jī)器寄存器。displace方法返回新的Point值。在一些實(shí)施例中,虛擬機(jī)104通過值而不是通過(不可見的)引用來返回Point。

在一些實(shí)施例中,像原生那樣,值類型可以引導(dǎo)重載。這里是與上面兼容的用于stringValueOf的一些重載:

使用Java作為示例,值類型的以上用法在若干方面不同于原生。

第一,用于成員選擇的點(diǎn)語(yǔ)法適用于值類型,如p.x或p.equals。諸如Java之類的一些語(yǔ)言中的原生根本不支持點(diǎn)語(yǔ)法。在一些實(shí)施例中,使用值類型來替換或補(bǔ)充表示原生的值類(諸如整數(shù)(Integer)),從而為針對(duì)在一些情況中是標(biāo)準(zhǔn)原生的類型(諸如整型、浮點(diǎn)型、雙精度型等)應(yīng)用方法打開大門。

第二,在一些實(shí)施例中,虛擬機(jī)104不提供對(duì)于諸如Point之類的由用戶定義的值類型的文本的支持。替代地,定義的構(gòu)造函數(shù)被調(diào)用以設(shè)置成分的值。在一些實(shí)施例中,為了確保封裝性,按成分的值創(chuàng)建除非由合適的構(gòu)造函數(shù)提供,否則不被虛擬機(jī)104允許。上面的示例使用關(guān)鍵字__MakeValue來標(biāo)記上面的兩個(gè)位置:新的Point值被創(chuàng)建的位置以及這種構(gòu)造函數(shù)被調(diào)用的位置。然而,替代的語(yǔ)法還可以被用于表示值類型構(gòu)造函數(shù),諸如“new Point”、“Point”以及空字符串。類似地,一些實(shí)施例不提供對(duì)于用于值類型的編譯時(shí)常量的支持。在其他實(shí)施例中,虛擬機(jī)104提供對(duì)于用戶定義的文本和常量表達(dá)式的支持。因此,在一些實(shí)施例中從被執(zhí)行以建立常量表達(dá)式的編譯時(shí)代碼構(gòu)建用戶定義的操作符。

第三,用于諸如Java之類的一些語(yǔ)言的內(nèi)置操作符是利用原生工作的主要方式,但是在一些實(shí)施例中這些內(nèi)置操作符不適用于Point。然而,用戶定義的操作符可以被用于提供功能等價(jià)物。一些例外可能是作用于每個(gè)種類的值的操作符,諸如關(guān)系操作符(==和?。?和字符串串接(+)。字符串串接可能是棘手的,因?yàn)樵谝恍?shí)施例中字符串串接在值類型駐留的類和原生類型之間的區(qū)分處被精確地精妙地重載。例如,如許多Java程序員通過試錯(cuò)法(trial and error)發(fā)現(xiàn)的,表達(dá)式("a"+1)+2和"a"+(1+2)具有不同的結(jié)果,因?yàn)榈谝粋€(gè)表達(dá)式首先轉(zhuǎn)換為字符串從而形成“a12”,而第二個(gè)表達(dá)式在加法后轉(zhuǎn)換為字符串從而形成“a3”。

在一些實(shí)施例中,關(guān)系操作符被當(dāng)作用于判等方法(類似于Java中的equals)的別名。另外,低級(jí)別的按位判等是另一種候選方法。然而,在一些實(shí)施例中,關(guān)系操作符可以潛在地導(dǎo)致值類型的裝箱形式和拆箱形式之間的行為差異,使用Java作為示例如下所示:

Point p1=__MakeValue(0,1);

Point p2=__MakeValue(1,0);

Point p3=__MakeValue(1,0);

assert(!p1.equals(p2));//值判等

assert(p1?。絧2);//再次值判等

assert(p2.equals(p3)&&p2==p3);

Object box1=p1,box2=p2,box3=p3;//將它們裝箱

assert(box1==box1);//x==x總成立(除了NaN(非數(shù)字))

assert(!box1.equals(box2));//Object.equals調(diào)用Point.equals

assert(box1?。絙ox2);//還必須是

assert(box2.equals(box3));

if(box2==box3)println("the cat died");//不確定

assert((Point)box2==(Point)box3);//返回到Point.equals

if(box2==(Object)p2)println("the cat died");//不確定

利用小調(diào)整,在Java中上面所有的測(cè)試可以在整型和整數(shù)(Integer)的情況下被重現(xiàn)。然而,對(duì)于一些小的整數(shù)值,由于Integer.valueOf工廠方法的特點(diǎn)而非原生、值類型或箱的內(nèi)在特征,貓不會(huì)存活。

第四,盡管原生不具有對(duì)應(yīng)于空引用的值,但是原生具有一般是零的默認(rèn)值。該默認(rèn)值在未初始化的字段和數(shù)組元素的初始內(nèi)容中出現(xiàn)。因此可以為每個(gè)值類型指定默認(rèn)值。例如,一種技術(shù)是將復(fù)合值設(shè)置為在其所有子字段中是遞歸默認(rèn)的。假如預(yù)定義的默認(rèn)值在諸如Java之類的一些語(yǔ)言中是固定值,則該約定適用于許多語(yǔ)言背景。

在一些實(shí)施例中,即使構(gòu)造函數(shù)從未創(chuàng)建默認(rèn)(全零位)的值類型,值類型定義中的方法的作者也可以向默認(rèn)的值類型提供行為,因?yàn)檫@些值類型在一些未初始化的變量中可以被觀察到。在實(shí)施例中,虛擬機(jī)104要么禁止無參數(shù)的構(gòu)造函數(shù)要么要求它們產(chǎn)生默認(rèn)值,以便于避免“決斗的默認(rèn)值”。

在一些實(shí)施例中,作為替代,虛擬機(jī)104通過強(qiáng)制包括公有的空構(gòu)造函數(shù)來迫使顯式地構(gòu)造默認(rèn)值,像這樣:public Point(){x=0;y=0;}。在公有的空構(gòu)造函數(shù)中,所有子字段被初始化為默認(rèn)值,否則編譯器102和/或驗(yàn)證器106將報(bào)告錯(cuò)誤??商娲?,虛擬機(jī)104可以不允許空構(gòu)造函數(shù),并且為默認(rèn)值保留其含義。

在一些實(shí)施例中,作為替代,虛擬機(jī)104允許通過對(duì)標(biāo)準(zhǔn)類定義施加的模式或語(yǔ)法來指定更精心制定的默認(rèn)值。然而,對(duì)此存在三點(diǎn)考慮:(1)在一些情況中默認(rèn)值將要求特殊的擴(kuò)展而不是簡(jiǎn)單的限制,(2)在一些情況中默認(rèn)值將包括特殊的規(guī)則以在來自空構(gòu)造函數(shù)的副作用的情況下編碼,以及(3)相比于全零位的約定,在運(yùn)行時(shí)應(yīng)用由用戶指定的默認(rèn)值可能潛在地具有更高的成本。

3.7示例性實(shí)現(xiàn)細(xì)節(jié)

在一些情況中,類的某些特征對(duì)于用于特定實(shí)施例的值類型將沒有意義。下文以問題和回答的格式表示根據(jù)特定實(shí)施例的用于值類型的設(shè)計(jì)和/或?qū)崿F(xiàn)決策。然而,下文所描述的回答不是決定性的;其他實(shí)施例可以提供對(duì)下文所呈現(xiàn)的問題的不同回答。因此,其他實(shí)施例對(duì)于每個(gè)問題可能有所不同。在一些實(shí)施例中,本節(jié)中所描述的關(guān)于值類型的限制在虛擬機(jī)104中被實(shí)現(xiàn)為供驗(yàn)證器106遵循的附加規(guī)則。

子類型化(subtyping)

值類可以擴(kuò)展引用類類型嗎?在大多數(shù)情況中,不可以。

引用類可以擴(kuò)展值類型嗎?在大多數(shù)情況中,不可以。

具體的值類可以擴(kuò)展另一值類型嗎?在大多數(shù)情況中,不可以。(因?yàn)榫唧w的值類是最終的。)

值類型定義可以是抽象的或非最終的嗎?在大多數(shù)情況中,不可以。

值類型定義可以實(shí)現(xiàn)接口嗎?可以。當(dāng)我們將值類看作接口實(shí)例時(shí),裝箱可以發(fā)生。

值類型可以參與基于繼承的子類型化嗎?在大多數(shù)情況中,不可以。(就像原生那樣。)

是否存在用于值的根類型(諸如Java中的Object超類型)?不一定。在一些實(shí)施例中,值類型的超類型可以被實(shí)現(xiàn)為模板化機(jī)制。

包含

值類型可以包含引用類型的字段嗎?可以。

引用類可以包含值類型的字段嗎?可以。

值類型可以包含值類型的成分字段嗎?可以。

數(shù)組可以包含值類型的元素嗎?可以。(在一些語(yǔ)言中,數(shù)組是對(duì)象的類型)。

值類型可以包含數(shù)組類型的字段嗎?可以。(例如,當(dāng)數(shù)組是對(duì)象時(shí))。

值類型可以包含非最終字段嗎?在許多實(shí)施例中,不可以,但是其他實(shí)施例可以允許具有非最終字段的值類型。

值類型的所有字段都必須是遞歸不變的嗎?不一定。(遞歸不變性是類型的獨(dú)立特征)。

值類型可以具有成員類型嗎?可以。(非靜態(tài)成員類型具有記錄包含值的隱藏字段)。

值類型可以是成員類型嗎?可以(如果它們是非靜態(tài)的,則它們具有指向包含對(duì)象的隱藏字段。)

當(dāng)創(chuàng)建值類型的數(shù)組時(shí),初始元素是什么?它們都是默認(rèn)的全零位值。(就像原生那樣。)

其類型是值類型的字段的初始值是什么?默認(rèn)的全零位值,直至第一次指派或初始化。

其類型是值類型的局部變量的初始值是什么?看情況,在一些實(shí)施例中指派規(guī)則禁止觀察這樣的值,直至第一次指派。

值類型可以包含其自身類型的字段嗎?在大多數(shù)情況中,直接地或間接地都不可以(類似于一些語(yǔ)言中的現(xiàn)有限制:類不能將其自身作為子類)。

兼容性

值類型是對(duì)象嗎?不一定,盡管值類型可以被裝箱成對(duì)象。

原生是值類型嗎?可能是。(值類型命名的整型、布爾型等將向包裝器類提供良好的繼承者,就像它們存在于諸如Java之類的當(dāng)前語(yǔ)言中那樣。)

值類型的數(shù)組是否為協(xié)變的?在大多數(shù)情況中,不是。(就像原生那樣,值類型箱的數(shù)組是協(xié)變的)。

值類型是否參與隱式轉(zhuǎn)換?在大多數(shù)情況中,不參與。(在一些實(shí)施例中,虛擬機(jī)104不需要實(shí)現(xiàn)隱式轉(zhuǎn)換,諸如Java中的int toUnsignedInteger)。

每個(gè)值類型都定義了類似對(duì)象的方法(toString等)嗎?有時(shí)是。在一些實(shí)施例中,虛擬機(jī)104需要類似對(duì)象的方法以使得它們的裝箱形式可以與期待對(duì)象而不是值類型的現(xiàn)有API互操作。然而,不是在所有實(shí)施例中都需要類似對(duì)象的方法。

是否存在用于這些方法的默認(rèn)的按成分的實(shí)現(xiàn)?是的。例如,用于箱的根類型是用來放置默認(rèn)的按成分的代碼的邏輯位置。

值類型可以被序列化嗎?看情況。在一些實(shí)施例中,為了阻止違背封裝性,虛擬機(jī)104不實(shí)現(xiàn)用于值類型的序列化。然而,在其他實(shí)施例中,虛擬機(jī)104可以實(shí)現(xiàn)用于值類型的序列化。

值類型的用戶可以請(qǐng)求原子性嗎?可以。在一些實(shí)施例中,可以使用諸如關(guān)鍵字volatile或_AlwaysAtomic之類的關(guān)鍵字指定原子性。

當(dāng)將值類型指派給泛型對(duì)象時(shí)發(fā)生了什么?虛擬機(jī)104基于值類型的類文件自動(dòng)將值類型裝箱到虛擬機(jī)104生成的類中。生成的類文件反映值類型的字段和方法,但是生成的對(duì)象包含頭部信息并且因此可以被用于標(biāo)識(shí)以及被用于與期待對(duì)象的API的互操作性。

當(dāng)空值被分配給值類型(或者與值類型相比較)時(shí)發(fā)生了什么?如果該值類型是裝箱的,則引用比較將返回不相等;如果值類型是拆箱的,則拋出異常。

封裝性

值類型可以具有非公有的字段嗎?可以。

值類型可以具有非公有的方法嗎?可以。

值類型可以具有靜態(tài)方法或字段嗎?可以。

值類型是怎樣構(gòu)造的?通過調(diào)用構(gòu)造函數(shù)。值類型構(gòu)造函數(shù)事實(shí)上是工廠方法,因此(使用JVM字節(jié)碼作為示例)在字節(jié)碼中不存在new;dup;init跳躍(dance)。

值類型的定義者可以要求其所有成分值的原子性嗎?可以。例如,通過在值類型定義中使用關(guān)鍵字或符號(hào),這些關(guān)鍵字或符號(hào)指示操作將始終是原子的。

值類型的封裝性可以被布置為排除所有默認(rèn)的按成分的操作嗎?可以。(例如,通過重載相關(guān)方法)。

值類型可以在不要求客戶機(jī)重新編譯的情況下改變尺寸或布局嗎?可以。

值類型的封裝性可以被布置為排除其所有字段是零的值嗎?在大多數(shù)情況中,不可以。(如上文所指出的,這是慎重的妥協(xié)。如上文所指出的,一些實(shí)施例中的默認(rèn)值可以與無參數(shù)的構(gòu)造函數(shù)值一致。)

諸如字節(jié)碼之類的虛擬機(jī)指令可以以訪問值類型的私有字段的方式被使用嗎?取決于實(shí)施例。

其他細(xì)節(jié)

是否存在對(duì)值類型的復(fù)雜度的限制?是的。在一些實(shí)施例中,虛擬機(jī)104對(duì)值類型的成分的數(shù)量和/或尺寸施加限制以便于做出性能保證。例如,但是不足夠低以做出性能保證。例如,值類型可以被限制為諸如255字之類的閾值。

虛擬機(jī)104支持通過拆分超類來重構(gòu)值類型嗎?在大多數(shù)情況中,不支持,除非虛擬機(jī)104允許抽象的值類型。

虛擬機(jī)104支持將方法重構(gòu)到值類型中或從值類型中將方法重構(gòu)出來嗎?支持,例如,與默認(rèn)方法的公共接口可以被用于該目的。

虛擬機(jī)104支持對(duì)于裝箱的值調(diào)用值類型的方法嗎?支持。在一些實(shí)施例中,虛擬機(jī)104自動(dòng)對(duì)值進(jìn)行裝箱和拆箱以創(chuàng)建用于API的橋。例如,當(dāng)使用Point時(shí),取決于上下文和環(huán)境,該表示將有時(shí)為值類型,有時(shí)為箱引用類型。

在一些實(shí)施例中,虛擬機(jī)104禁止值類型的子類化和子類型化以避免指針多態(tài)性。抽象超類型(比如Java中的接口Comparable)可以被考慮,因?yàn)樗鼈儾荒鼙粚?shí)例化。結(jié)果,虛擬機(jī)104可以因此確保所有方法以方法接收者的確切類型被明確地解析。在一些情況中,該決策還回避了值類型數(shù)組的問題,如果數(shù)組可以包含(例如)2字段Point和3字段ColoredPoint(染色點(diǎn))值,則值類型數(shù)組可以包括尺寸可變的元素。對(duì)于數(shù)組,由于原生數(shù)組已經(jīng)具有完全同構(gòu)的元素,因此依賴原生語(yǔ)義是方便的。然而,該方法不是沒有問題。例如,對(duì)于實(shí)現(xiàn)Comparable的值類型Bignum,虛擬機(jī)104可以允許箱的數(shù)組Bignum.__BoxedValue[]是接口數(shù)組Comparable[]的子類型,但是在一些實(shí)施例中扁平的數(shù)組類型Bignum[]不能也是Comparable[]的子類型。

3.8示例性字節(jié)碼和類型描述符

存在可以在虛擬機(jī)104的指令集(例如,字節(jié)碼)中顯現(xiàn)值類型的許多方式。例如,用于值類型的全新指令可以通過將值類型當(dāng)作全新的結(jié)構(gòu)體或者重載現(xiàn)有指令以接受值類型或引用來實(shí)現(xiàn)。本節(jié)關(guān)注可以被實(shí)現(xiàn)為生成、加載、存儲(chǔ)和/或以其他方式操縱值類型的新指令。然而,如上文提到的,其他實(shí)施例可以重載現(xiàn)有指令以實(shí)現(xiàn)類似的效果。

建立在上面“示例性類文件結(jié)構(gòu)”中所討論的描述符示例上,存在用于原生的單字母類型描述符(例如,用于整型的I)、用于類的“L”描述符(例如,L ClassName),并且對(duì)于任何類型,可以通過追加“[”來為該類型的數(shù)組導(dǎo)出類型描述符。在實(shí)施例中,為值類型添加另一形式;用于值類型com.foo.Bar的類型描述符將會(huì)是Q com/foo/Bar;這就像用于引用類型的“L”描述符一樣,除了不同的符號(hào)“Q”。例如,考慮以下方法:

public static double getR(Point p){...}

用于以上方法的簽名將會(huì)是(Q Point)D,這指示它采用值類型Point的單個(gè)參數(shù)并且返回雙精度型。

新虛擬機(jī)104指令的示例以如下格式描述:

//描述

opcode[constant pool operands]stack operands->stack result

在一些實(shí)施例中,對(duì)于所有操作碼,“qdesc”是用于值類型的Q描述符。然而,對(duì)于許多指令,驗(yàn)證器106可以從指令的上下文推斷描述符。因此,如果這樣的描述符可以替代地通過上下文來推斷,則一些實(shí)施例可以選擇忽略來自指令的這種描述符。用于局部變量401的表槽(slot)和用于操作數(shù)棧402的表槽可以保持值類型以及原生或引用。

在一些實(shí)施例中,值類型消耗局部變量401和/或操作數(shù)棧402中的單個(gè)槽。因此,每個(gè)槽不必具有固定長(zhǎng)度的尺寸。然而,在其他實(shí)施例中,值類型消耗多個(gè)槽,類似于在一些JVM實(shí)現(xiàn)中諸如雙精度型之類的尺寸過大的原生類型如何被設(shè)計(jì)為占用兩個(gè)槽而不是一個(gè)槽,從而使得槽可以具有相等的尺寸。在一些實(shí)施例中,虛擬機(jī)104可以在不重新編譯代碼的情況下改變槽的尺寸和布局。后面的節(jié)中討論關(guān)于虛擬機(jī)存儲(chǔ)器布局300內(nèi)的值類型的存儲(chǔ)的附加細(xì)節(jié)。

在實(shí)施例中,為了操縱棧幀400上的值類型,虛擬機(jī)104支持以下指令。同樣,盡管以下示例中的一些形式可以認(rèn)為是不必要的,但是示例顧及到明確性和完整性。因此,在一些實(shí)施例中,新指令的數(shù)量可以遠(yuǎn)小于下文所描述的新指令的數(shù)量。

//從局部變量加載值類型

vload[qdesc?,index]->value type

//將值類型存儲(chǔ)到局部變量中

vstore[qdesc?,index]value type->

//創(chuàng)建值類型的新數(shù)組

vnewarray[qdesc]size->arrayref

//將值類型存儲(chǔ)到數(shù)組中

vastore[qdesc?]arrayref,index,value type->

//從數(shù)組加載值類型

vaload[qdesc?]arrayref,index->value type

//提取來自值的成分

vgetfield[field-desc]value type->result

//將成分插入到值類型中(為了構(gòu)造函數(shù)的私有使用)

vputfield[field-desc]value argument->value type

//構(gòu)建具有全部默認(rèn)的成分的新生值類型(為了構(gòu)造函數(shù)的使用)

vnew[qdesc]->value type

//對(duì)值類型調(diào)用方法

vinvoke[method-desc]value type,(argument)*->(return)?

//返回值類型

vreturn[qdesc?]value type

在一些實(shí)施例中,虛擬機(jī)104支持可以對(duì)任何類型的幀400內(nèi)容操作的若干“多態(tài)的”指令,諸如JVM字節(jié)碼集中的“dup”;這些指令可以被擴(kuò)展為同樣支持值類型。在大多數(shù)情況中,這些多態(tài)指令可以用最少的努力被重載到現(xiàn)有指令上。使用JVM指令碼集作為示例,vinvoke功能可以被重載到invokestatic上,而vgetfield功能可以被重載到getfield上。

在一些實(shí)施例中,上文提到的字段和方法描述符將會(huì)是常量表201引用,諸如指代方法引用結(jié)構(gòu)207、字段引用類型206和/或類信息結(jié)構(gòu)203的引用。在一些實(shí)施例中,描述符的成分通過值類型的標(biāo)稱名稱(例如,沒有任何“Q”前綴)指代值類型。對(duì)應(yīng)類的裝箱形式具有例如從描述符語(yǔ)言(例如,L Foo)導(dǎo)出的它們自己的字節(jié)碼名稱。在一些實(shí)施例中,虛擬機(jī)104支持克隆常量表201類型,諸如CONSTANT_ValueMethodref,使用Java類文件作為示例。

在一些實(shí)施例中,值類型中的靜態(tài)方法重復(fù)使用為適當(dāng)?shù)念悓?shí)現(xiàn)的相同指令,而不需要特別指向到值類型的特殊指令。例如,使用JVM字節(jié)碼集作為示例,可以使用invokestatic來調(diào)用值類型中的靜態(tài)方法。在一些實(shí)施例中,類似于靜態(tài)方法,靜態(tài)字段可以重復(fù)使用由虛擬機(jī)104實(shí)現(xiàn)的用于操縱靜態(tài)字段的相同指令來操縱適當(dāng)類的靜態(tài)字段。

在一些實(shí)施例中,虛擬機(jī)104阻止構(gòu)造函數(shù)調(diào)用通過引用傳遞要構(gòu)造的值類型。替代地,值類型構(gòu)造函數(shù)被實(shí)現(xiàn)為將作為靜態(tài)方法被調(diào)用的靜態(tài)工廠方法。用于成分初始化的各變化步驟通過特權(quán)指令vputfield的使用而被內(nèi)部地呈現(xiàn)給構(gòu)造函數(shù),該特權(quán)指令vputfield與為用于初始化屬性對(duì)象的最終字段的構(gòu)造函數(shù)保留的特殊指令(諸如JVM字節(jié)碼中的putfield)等效地操作。要注意vputfield返回更新后的值,因此不存在副作用發(fā)生的機(jī)會(huì)。

在一些實(shí)施例中,虛擬機(jī)104將如構(gòu)造函數(shù)使用的vnew和vputfield操作符的效果結(jié)合到vpack指令中,vpack指令將會(huì)采用棧上的一系列成分。這些成分的順序和類型將由包含值類型定義隱式地定義。這將使得一些簡(jiǎn)單的構(gòu)造函數(shù)稍微更加緊湊,但是可能導(dǎo)致虛擬機(jī)104中實(shí)現(xiàn)的指令及其包含類之間的新型耦合。在一些實(shí)施例中,虛擬機(jī)104對(duì)作為命名字段的簇(cluster)的復(fù)合類型進(jìn)行操作,而不是對(duì)入棧的值的有序元組進(jìn)行操作。在一些情況中,如果每個(gè)字段初始化具有其自己的vputfield操作碼,則虛擬機(jī)104指令和源代碼之間的對(duì)應(yīng)關(guān)系可以更易于追蹤。

在一些實(shí)施例中,當(dāng)從較高級(jí)別的指令生成較低級(jí)別的指令時(shí),改變某個(gè)值類型的值內(nèi)的字段的一個(gè)或多個(gè)較高級(jí)別的指令可以被識(shí)別。該值可以是例如潛在地具有多個(gè)不同的成分字段的值類型的實(shí)例。本文描述了這種值類型的示例,諸如點(diǎn)(Point)或復(fù)數(shù)(Complex)??梢源_定的是,在較低級(jí)別的指令的上下文中,用于該值的至少一個(gè)成分字段的數(shù)據(jù)將被集體存儲(chǔ)在單個(gè)容器內(nèi)。例如,字段可以被存儲(chǔ)為其對(duì)應(yīng)的子值的拆箱表示,而不是對(duì)存儲(chǔ)相應(yīng)子值的其他容器(多個(gè)容器)的引用。響應(yīng)于該確定,生成單個(gè)較低級(jí)別的指令。這種較低級(jí)別的指令的一個(gè)示例是本文所描述的vputfield指令。

在一些實(shí)施例中,所生成的單個(gè)較低級(jí)別的指令被配置為命令解釋器108識(shí)別與字段對(duì)應(yīng)的容器的一部分,諸如一個(gè)或多個(gè)位。單個(gè)較低級(jí)別的指令還被配置為命令解釋器108根據(jù)一個(gè)或多個(gè)較高級(jí)別的指令來改變?cè)摬糠帧WR(shí)別和/或改變可以至少部分基于與值的值類型相關(guān)聯(lián)的元數(shù)據(jù)。例如,指令可以使得解釋器108使用用于值類型的字段定義來定位該部分和/或?qū)嵭杏糜趯?duì)應(yīng)的值類型定義的訪問控制信息、類型檢查等等。在實(shí)施例中,單個(gè)較低級(jí)別的指令命令解釋器108在不使用指針定位字段的情況下和/或在不必發(fā)出使值開放到其成分字段中的分開指令的情況下進(jìn)行該操作。

在實(shí)施例中,可選擇性地通過重新排序、合并或分開彼此相關(guān)并且與可以讀或?qū)懘鎯?chǔ)在容器中的值或容器的至少一些成分字段的任何其他指令相關(guān)的兩個(gè)或更多個(gè)這種較低級(jí)別的指令的效果來生成較低級(jí)別的指令。這種效果的重新排序、合并或分開可以受保護(hù)存儲(chǔ)在容器中的值的每個(gè)成分字段以及存儲(chǔ)在容器中作為整體的值的一致性的規(guī)則影響。因此,技術(shù)可以包括使用分層的數(shù)據(jù)結(jié)構(gòu)的嵌套存儲(chǔ)器模型,當(dāng)對(duì)象拆分成值時(shí),其可以拆分成更小的值并且最終一直向下拆分成成分原生和引用。

根據(jù)實(shí)施例,一種方法包括:當(dāng)解釋諸如Java字節(jié)碼之類的指令時(shí),識(shí)別指令以將第一個(gè)較小的值作為第二個(gè)較大的值的字段插入。該指令可以是例如單個(gè)較低級(jí)別的指令,諸如上面生成的指令。第二個(gè)值可以是例如具有集體存儲(chǔ)在容器中的多個(gè)不同成分字段的經(jīng)定義的值類型的值。第一個(gè)值可以是例如對(duì)應(yīng)于字段的子值。在實(shí)施例中,確定第二個(gè)值具有某個(gè)值類型?;谂c某個(gè)值類型相關(guān)聯(lián)的元數(shù)據(jù),對(duì)應(yīng)于字段的第二個(gè)值的一部分被定位,并且第一個(gè)值被加載到該部分中。這可以包括例如基于與某個(gè)值類型相關(guān)聯(lián)的值類型定義數(shù)據(jù)來實(shí)行訪問控制信息和類型檢查,和/或使用值類型定義數(shù)據(jù)來定位相關(guān)部分。在實(shí)施例中,選擇性地通過重新排序、合并或分開兩個(gè)或更多個(gè)這種較低級(jí)別的指令的效果來生成較低級(jí)別的指令,諸如上文所描述的。

3.9裝箱和對(duì)象互操作性

在實(shí)施例中,每個(gè)值類型具有對(duì)應(yīng)的箱類,就像在Java中Integer是用于整型的箱類型。在一些實(shí)施例中,虛擬機(jī)104或編譯器102從用于值類型的類文件中所提供的定義自動(dòng)導(dǎo)出用于值類型的箱類的類文件(或者反之亦然),而不是要求值類型及其對(duì)應(yīng)的箱的分開編碼。例如,方法和字段可以從值類的類文件得到,但是其中箱類文件包含標(biāo)識(shí)符,該標(biāo)識(shí)符指示虛擬機(jī)104應(yīng)當(dāng)將箱類文件解釋為指代適當(dāng)?shù)膶?duì)象類。箱類文件還可以包含可以不存在于值類型的類文件中的附加的元數(shù)據(jù),諸如超類(例如,Java中的Object超類)的存在。可替代地,虛擬機(jī)104可以生成對(duì)于值類型和箱表示這二者通用的一個(gè)類文件,其中類文件取決于上下文而被虛擬機(jī)104不同地處理。例如,如果值類型使用描述符“Q Foo”,則用于對(duì)應(yīng)的箱類的描述符可以是“L Foo”。對(duì)于這兩種類型,虛擬機(jī)104將知道尋找被稱為Foo的類文件并且基于哪個(gè)描述符被使用來生成值視圖或引用視圖。

在一些實(shí)施例中,諸如構(gòu)建之類的公共操作具有用于值類型或箱類的不同機(jī)制。例如,編譯器102可以生成多個(gè)版本的類工件(class artifact)(例如,具有簽名(...)V的標(biāo)準(zhǔn)構(gòu)造函數(shù)和具有簽名(...)Q Foo的值構(gòu)造函數(shù))或者虛擬機(jī)104將根據(jù)需要從其中一個(gè)的指令導(dǎo)出另一個(gè)。在一些實(shí)施例中,對(duì)于值類型Foo,F(xiàn)oo可以被寫為指代值形式,而Foo.__BoxedValue被寫為指代Foo的裝箱形式。

在實(shí)施例中,值類型的裝箱表示和拆箱表示之間的轉(zhuǎn)換像諸如Java之類的一些語(yǔ)言中當(dāng)前的原生箱(例如,valueOf(boxed))那樣通過遵循命名約定的方法來表示,或者可以由像下面的轉(zhuǎn)換指令來表示:

//將值裝箱

v2a[qdesc]value->ref

//將值拆箱

a2v[qdesc]ref->value

值之間的比較(類似于JVM字節(jié)碼集中的acmp和icmp字節(jié)碼)也可以由遵循命名轉(zhuǎn)換的方法來表示,或者用像下面的特殊指令來表示:

//使用按成分的、按位的以及引用判等來比較兩個(gè)值

vcmp[qdesc?]value,value->boolean

在一些實(shí)施例中,盡管在一些情況中像操縱原生和引用的指令那樣處理新的值類型指令的“克隆”是有用的,但是在實(shí)施例中轉(zhuǎn)換和比較指令可以使用方法調(diào)用(例如,vinvoke)來實(shí)現(xiàn)。

在一些實(shí)施例中,像數(shù)組那樣,箱類由虛擬機(jī)104生成。在實(shí)施例中,系統(tǒng)將箱代碼盡量多地分解為常見的抽象超類。在Java中,這大約是為經(jīng)典對(duì)象采取的方法,其中默認(rèn)行為在java.lang.Object中找到。

3.10示例性代碼

示例:構(gòu)造

在本節(jié)中使用上面在“新字節(jié)碼和類型描述符”中介紹的新指令與來自JVM字節(jié)碼集的指令的組合來描述創(chuàng)建和使用值類型的示例。盡管JVM字節(jié)碼被用于提供示例,但是由示例描述的技術(shù)不限制于Java、JVM或任何特定語(yǔ)言或虛擬機(jī)架構(gòu)。

在一些實(shí)施例中,通過首先執(zhí)行創(chuàng)建未初始化的對(duì)象的指令并且然后調(diào)用構(gòu)造函數(shù)來初始化對(duì)象。用于值類型的構(gòu)造函數(shù)的行為與工廠方法更類似。下面示出了為Point的構(gòu)造函數(shù)生成的示例性指令。

為了在棧幀400的局部變量401中創(chuàng)建Point的實(shí)例,工廠方法被調(diào)用,并且結(jié)果被存儲(chǔ)在本地:

在上面的示例中,為了簡(jiǎn)化闡述,值類型的構(gòu)造函數(shù)的名稱被更改為<new>,以強(qiáng)調(diào)該構(gòu)造函數(shù)是工廠方法。

示例:嵌套值

在上面的示例中,當(dāng)讀取嵌套值時(shí),首先讀取它的封閉值。

示例:數(shù)組

在實(shí)施例中,利用vnewarray指令來創(chuàng)建數(shù)組,并且非常像任何其他數(shù)組類型那樣操縱數(shù)組。以下是示例:

示例:方法調(diào)用

在實(shí)施例中,靜態(tài)地解析對(duì)于值類型的方法。invokestatic指令對(duì)于調(diào)用值類型的靜態(tài)方法和非靜態(tài)方法這二者(作為指令/字節(jié)碼語(yǔ)法)將會(huì)是足夠的,但是為了清楚地闡述,一些實(shí)施例對(duì)于值類型的非靜態(tài)方法使用新的調(diào)用指令vinvoke。以下是示例:

示例:裝箱

在一些實(shí)施例中,當(dāng)值類型被指派了類型Object、它的箱類型或它實(shí)現(xiàn)的接口類型的變量時(shí),變量的內(nèi)容由編譯器102和/或虛擬機(jī)104自動(dòng)裝箱。例如:

示例:拆箱

在實(shí)施例中,當(dāng)值類型從類型Object、它的箱類型或它實(shí)現(xiàn)的接口類型的變量被分配時(shí),首先檢查引用以查看它是否是對(duì)應(yīng)的箱類型,并且(如果是的話)然后值被拆箱。以下是示例:

在一些實(shí)施例中,裝箱引用具有對(duì)它直接調(diào)用的值類型的方法,例如:

示例:扁平化的散列表

在一些實(shí)施例中,因?yàn)橹殿愋蜎]有指針,所以值類型可以被用于通過移除間接尋址的級(jí)別來使一些數(shù)據(jù)結(jié)構(gòu)扁平化。扁平化不僅移除了來自關(guān)鍵路徑的依賴性負(fù)載,而且(典型地)將相關(guān)數(shù)據(jù)移動(dòng)到相同的高速緩存線上。

在一些情況中,調(diào)優(yōu)良好的、尺寸可變的散列表可以在不超過兩個(gè)高速緩存線引用中答復(fù)查詢,其中一個(gè)引用用來針對(duì)表尺寸咨詢表頭部,一個(gè)引用用來探查表中的條目。如果表?xiàng)l目在承載表的數(shù)據(jù)數(shù)組內(nèi)是扁平化的,則這可以實(shí)現(xiàn),并且在值類型的幫助下這成為可能。

上面的代碼實(shí)際上觸摸了三個(gè)高速緩存線,以便于從數(shù)組頭部提取數(shù)組長(zhǎng)度。在一些實(shí)施例中,解決該問題包括將數(shù)組長(zhǎng)度向上提升到散列表頭部中。

上面的代碼避開將具有默認(rèn)值的條目(零散列、空字符串引用)與尋找條目失敗區(qū)分開的問題。這是使面向指針的算法(例如,在Java中)適應(yīng)于值類型的典型問題。這可以由不同的實(shí)施例以若干方式解決。一種方式是引入表達(dá)可選擇的條目(條目加上布爾型)的值,并且從getEntry返回該值。要注意在用于getEntry的慢路徑的末端處,實(shí)現(xiàn)默認(rèn)(空)條目值的能力在此可以是有用的。出于上面給出的原因,默認(rèn)值是一些語(yǔ)言景觀(諸如Java)的部分。

在上面的示例中,__AlwaysAtomic關(guān)鍵字的效果是確保數(shù)組元素值在沒有內(nèi)部競(jìng)爭(zhēng)的情況下被一致地讀取。在沒有該修改的情況下,在一些平臺(tái)上,結(jié)構(gòu)撕裂可能導(dǎo)致值可能與錯(cuò)誤的鍵相關(guān)聯(lián)的狀態(tài)。該危害來自扁平化;它在數(shù)據(jù)結(jié)構(gòu)的“指針豐富的”版本中不會(huì)呈現(xiàn)。

在一些實(shí)施例中,計(jì)算平臺(tái)能夠借助于64位存儲(chǔ)器引用來在沒有額外成本的情況下實(shí)現(xiàn)用于該數(shù)據(jù)結(jié)構(gòu)的原子性。這假設(shè)值成分可以被打包為32位,這是通常的情況。在一些情況中,甚至四個(gè)成分的值可以容納在128位中,并且大多數(shù)硬件平臺(tái)以合理的成本提供原子的128位讀和寫。對(duì)于較大的值,比如具有五個(gè)或更多個(gè)成分的值,用于原子性的成本將急劇增加,這是原子性不是默認(rèn)的原因。

要注意為了對(duì)于整型和字符串型起作用,該示例性數(shù)據(jù)結(jié)構(gòu)是“硬連線的”。對(duì)應(yīng)的泛型類將從扁平化的數(shù)組獲得一些益處,但是可以不直接對(duì)拆箱的整型起作用。在一些實(shí)施例中,虛擬機(jī)104實(shí)現(xiàn)類似模板的機(jī)制來對(duì)非引用進(jìn)行參數(shù)化以解決該問題。

示例:比較

如上文所指出的,在一些實(shí)施例中值類型可以實(shí)現(xiàn)接口。這是支持比較的值類型的示例:

自動(dòng)創(chuàng)建的箱類適當(dāng)?shù)貙?shí)現(xiàn)接口,橋接到所給出的compareTo方法。vinvoke指令還可以直接調(diào)用如所編寫的compareTo方法。

這是對(duì)接口函數(shù)的調(diào)用的一些示例。

像類那樣,通常存在對(duì)實(shí)現(xiàn)接口的方法做出直接的、無接口的調(diào)用(在該情況中vinvoke)的選項(xiàng)。

在上面的示例中,接口(諸如根據(jù)Java的當(dāng)前規(guī)則)采用擦除的Object參量。在值類型的背景下,允許類型參量(Comparable<T>中的T)綁定到值類型Bignum并且因此將箱方法一直橋接到方法compareTo。

在一些實(shí)施例中,每個(gè)值類型實(shí)現(xiàn)自組織(ad hoc)接口或抽象超類型,諸如下面的示例:

3.11附加的示例性選項(xiàng)

子類型化。在一些實(shí)施例中,虛擬機(jī)104創(chuàng)建用于值類型的新的根類型以支持用于解析的抽象值超類型。

擦除vs.具體化。在實(shí)施例中,箱僅對(duì)箱操作,而值類型僅對(duì)值類型操作。某些橋方法由虛擬機(jī)104(靜態(tài)地或者動(dòng)態(tài)地)自動(dòng)生成。

按成分方法。在一些實(shí)施例中,按成分方法是默認(rèn)的。例如,過度健談的toString方法可能徹底違背秘密值成分的封裝性。用于生成用于打印、比較、散列碼等的按成分方法的機(jī)制和策略可以為了選擇性加入(opt-in)vs.選擇性退出(opt-out)的正確混合而被平衡。

增強(qiáng)的變量操作。在一些實(shí)施例中,比較和交換(CAS)和類似的操作作為直接暴露CAS操作的單獨(dú)特征的部分而被解決。在一些實(shí)施例中,在許多情況下值類型與引用和原生一起合并到CAS和類似的操作中。

值/原生收斂(convergence)。在實(shí)施例中,原生被集成到值類型中(例如,__ByValue class int{...}),并且成為預(yù)定義的值類型。

按字段的副作用。在一些實(shí)施例中,為了簡(jiǎn)化,值字段是被定為最終的。然而,在其他實(shí)施例中,值字段可以不一定總是最終的。在一些實(shí)施例中,可以對(duì)值中的僅一個(gè)字段產(chǎn)生副作用,從而實(shí)現(xiàn)“通過值”的所有效率以及“通過引用”的所有可變性。

值上泛型。在一些實(shí)施例中,虛擬機(jī)104支持用于值類型的泛型(例如,List<Point>)。

數(shù)組值。聚合的空間形成2×2的矩陣{標(biāo)識(shí),無標(biāo)識(shí)}×{同構(gòu),異構(gòu)}。對(duì)象和數(shù)組填充“標(biāo)識(shí)”行;值類型填充(無標(biāo)識(shí),異構(gòu))箱;剩余的箱可以被描述為數(shù)組值。在一些實(shí)施例中,虛擬機(jī)104提供對(duì)于數(shù)組值的支持。

3.12從類型到值類型的遷移

在諸如Java之類的一些操作環(huán)境中,如果設(shè)施在許多之前實(shí)現(xiàn)的類型寫入時(shí)已經(jīng)是可用的(例如,Java中的LocalDateTime、Integer等),假設(shè)在已經(jīng)是值類型的時(shí)間處這些類型已經(jīng)是可用的,則許多之前實(shí)現(xiàn)的類型可能應(yīng)當(dāng)已經(jīng)是值類型。在一些實(shí)施例中,虛擬機(jī)104支持將以上提到的類型實(shí)現(xiàn)為值類型的能力同時(shí)維持API互操作性。

遷移兼容性具有兩個(gè)重要的方面:二進(jìn)制兼容性(當(dāng)現(xiàn)有的二進(jìn)制指代預(yù)先遷移的類型時(shí),二進(jìn)制兼容性發(fā)生)以及源兼容性(當(dāng)針對(duì)遷移的類型重新編譯文件時(shí),源兼容性發(fā)生)。源兼容性一般要求當(dāng)引用類型被遷移為值類型時(shí),對(duì)該引用類型的每個(gè)操作具有兼容的含義;這不僅包括像構(gòu)造和方法調(diào)用那樣的值安全的慣用語(yǔ)法,而且包括諸如鎖定之類的值不安全的操作,因?yàn)楝F(xiàn)有代碼可能執(zhí)行依賴標(biāo)識(shí)的操作。

假如預(yù)先存在的類型“WasARef”被遷移為值類型,并且由遷移注釋為:

__Migrated__ByValue class WasARef{...}

以下事實(shí)幫助兼容性,即如果類“X”從引用類型遷移為值類型,則類型描述符“L X;”在遷移后仍然是合法的類型,它指代現(xiàn)在的值類型的裝箱形式。如上文所討論的,用于值類型的裝箱版本的類文件可以從值類型的類文件生成?;蛘哌@二者可以共享公共的類文件。因此,只要維持了命名約定,那么導(dǎo)致類型不安全的操作或使用的對(duì)值類型的先前使用可以替代地利用值類型的裝箱版本。因此,為了提供用于遷移的類型的源兼容性,在一些實(shí)施例中虛擬機(jī)104通過提供從“L”橋接到“Q”形式的橋方法來至少為遷移的所有值類解決值不安全的操作,以使得重新編譯的API繼續(xù)與舊客戶機(jī)工作。

3.13更新字段的值

在實(shí)施例中,虛擬機(jī)104被配置為針對(duì)當(dāng)更新一個(gè)字段和一些其他字段是易變的時(shí)可能出現(xiàn)的問題而使用指令的替代設(shè)計(jì):

例如,如果代碼顯示為:

kludge k;

k.baz=7;

那么按照語(yǔ)句與以下語(yǔ)句同義的理論

k=kludge(k.flag,7);

可以寫入“flag”字段。在實(shí)施例中,虛擬機(jī)104提供對(duì)于具有可以獨(dú)立寫入的兩個(gè)易變字段的“像值一樣的”結(jié)構(gòu)的支持。然而,為了彌補(bǔ),源語(yǔ)言可以在語(yǔ)言級(jí)別實(shí)現(xiàn)更精心制定的語(yǔ)義。例如,源語(yǔ)言可以遵循諸如“當(dāng)且僅當(dāng)值類型是變量的值時(shí),值類型的字段是變量”之類的規(guī)則。因此,如果以下語(yǔ)句是合法的,

c.im=7;

則以下語(yǔ)句是不合法的:

myComplexHashMap.get(key).im=7;

只要在更新變量的字段時(shí)保持變量中的復(fù)數(shù)值,那么編碼員可以在使用用于復(fù)數(shù)的值類和非值類之間高效地來回移動(dòng)。

同時(shí),能夠獨(dú)立寫入值的兩個(gè)(可能易變的)字段中的每個(gè)字段的虛擬機(jī)104指令可以被提供。因此,在一些實(shí)施例中,以下技術(shù):不向上面介紹的那些添加新的虛擬機(jī)104指令,卻將作為vstore或vastore指令的部分的“desc”從

Q-descriptor

概括為

Q-descriptor(.field-name)*

結(jié)果,描述符可以不僅描述值類型,而且可以描述該值類型的任何字段或子字段。

按照該方法,編譯

c.im=7;

的示例性方式是

bipush 7

vstore"Qcomplex;.im"3

而編譯

c.im*=trouble();

的示例性方式是

vload 3//c

vgetfield"Qcomplex;.im"

invokewhatever"trouble"

mul

vstore"Qcomplex;.im"3

因此,如果vload和vaload被擴(kuò)展(以及可能vreturn和vgetfield和vputfield被擴(kuò)展)以采用這些擴(kuò)展的描述符(也可能為了對(duì)稱),則它變成:

vload"Qcomplex;.im"3

invokewhatever"trouble"

mul

vstore"Qcomplex;.im"3

如果p是具有被命名為“phase”的類型復(fù)數(shù)的字段的值類型“foo”的變量,則編譯

p.phase.im*=trouble();

的示例性方式是

vload"Qfoo;.phase.im"4

invokewhatever"trouble"

mul

vstore"Qfoo;.phase.im"4

該方法在某些方面比vputfield/dup_X1跳躍更高效。用于將看上去像是鏈?zhǔn)阶侄卧L問的東西打包成單個(gè)描述符的正當(dāng)理由是它畢竟只是個(gè)描述符;它解析為單個(gè)偏移并且在一些實(shí)施例中使用它的vload或vstore僅執(zhí)行對(duì)存儲(chǔ)器的一次讀或?qū)懖僮鳌?/p>

在一些實(shí)施例中,類型檢查彌補(bǔ)了上面所描述的技術(shù)。例如,對(duì)于vload"Qfoo;.phase.im"4,局部變量槽4中的數(shù)量的類型必須是Qfoo;,但是加載到棧上的元素具有與子字段的類型.phase.im相等的類型,它可以是雙精度型或整型,這取決于復(fù)數(shù)的實(shí)現(xiàn)。

4.0修改后的加載進(jìn)程

在一些實(shí)施例中,虛擬機(jī)104修改上文在“加載、鏈接和初始化”中所描述的加載進(jìn)程來彌補(bǔ)值類型的引入。本節(jié)描述所述技術(shù)可以被修改的若干示例性方式。然而,示例僅適用于特定實(shí)施例并且不是決定性的。

如上文所描述的,當(dāng)類文件200被加載到虛擬機(jī)存儲(chǔ)器布局300中時(shí),存儲(chǔ)器被分配給所加載的類的靜態(tài)字段。在類的靜態(tài)字段具有值類型的情況下,然后在一些實(shí)施例中,需要被分配的空間量位于用于值類型的類文件中而不是在用于當(dāng)前類的類文件中。結(jié)果,虛擬機(jī)104基于為被加載的類的類文件中的字段指定的符號(hào)引用來定位值類的類文件,并且計(jì)算所需要的存儲(chǔ)器的量。不過,如果用于值類的類文件已經(jīng)被加載,則虛擬機(jī)104可以執(zhí)行計(jì)算并且在與指示總尺寸的值類相關(guān)聯(lián)的元數(shù)據(jù)中高速緩存結(jié)果。該元數(shù)據(jù)然后可以被虛擬機(jī)104讀取,而不是多次執(zhí)行計(jì)算。例如,需要由虛擬機(jī)104為該字段在共享區(qū)域301中分配的空間量將是值類型的成分的和。這具有如下警告,即如果值類型具有值類型的字段(假設(shè)實(shí)施例允許這樣的字段),則所需要的存儲(chǔ)器的計(jì)算被遞歸地執(zhí)行,對(duì)總數(shù)進(jìn)行合計(jì)。

類似地,如果所加載的類的實(shí)例在堆302上被創(chuàng)建,則用于保持值類型的實(shí)例字段的所需要的空間量可以以相同的方式計(jì)算??商娲兀撚?jì)算可以提前執(zhí)行并且高速緩存為與值類型和/或?qū)ο箢愊嚓P(guān)聯(lián)的元數(shù)據(jù),以防止虛擬機(jī)104必須在每次實(shí)例化對(duì)象類時(shí)執(zhí)行計(jì)算。

5.0存儲(chǔ)考慮

如上文所討論的,值類型打算使用扁平化表示來存儲(chǔ)并且通過值傳遞。因此,當(dāng)在保持值類型的堆302上創(chuàng)建對(duì)象時(shí),值類型的內(nèi)容被存儲(chǔ)在對(duì)象內(nèi),而不是被分配在堆302上的單獨(dú)區(qū)域中的對(duì)值類型的引用。此外,當(dāng)值類型被加載到棧幀400中時(shí),是值類型的內(nèi)容被復(fù)制到局部變量401和/或操作數(shù)棧402中,而不是引用。

在一些實(shí)施例中,局部變量401表示保持一個(gè)或多個(gè)“容器”的數(shù)據(jù)結(jié)構(gòu),諸如保持若干槽以存儲(chǔ)用于局部變量401的各個(gè)值的數(shù)組。分配用于局部變量401的空間的一種技術(shù)是分配具有固定尺寸的容器。例如,虛擬機(jī)104可以分配數(shù)組,在該數(shù)組中每個(gè)槽被設(shè)定尺寸以適配原生或引用。因此,原生通過值被存儲(chǔ)在槽中,而非原生被分配在堆302上并且在槽中存儲(chǔ)對(duì)堆302的引用。在一些情況中,表示多個(gè)其他原生的原生(諸如雙精度型)被看作占用多個(gè)槽。然而,值類型由用戶定義并且因此可以具有可能不整齊地適配固定尺寸的容器的可變尺寸。

在一些實(shí)施例中,諸如當(dāng)JIT編譯器109接管并且編譯正被執(zhí)行的一個(gè)或多個(gè)方法的虛擬機(jī)104指令時(shí),執(zhí)行代碼的全局分析。結(jié)果,虛擬機(jī)104可以確定執(zhí)行特定的經(jīng)編譯的方法將需要的容器尺寸。然而,當(dāng)使用解釋器108時(shí),虛擬機(jī)104在沒有全局分析的益處的情況下一次一個(gè)指令地執(zhí)行程序。因此,當(dāng)棧幀400(例如,作為方法調(diào)用的結(jié)果)被創(chuàng)建時(shí)所分配的用于局部變量401的容器可能被設(shè)定了不足以處理特定值類型的尺寸。例如,假設(shè)局部變量401包括兩個(gè)容器,各自分配了64位的存儲(chǔ)器。如果給定方法的虛擬機(jī)104指令指定將諸如整型之類的較小的值存儲(chǔ)到第一容器中,則存儲(chǔ)器分配可能是低效的(分配多于需要的空間),但是整型可以被存儲(chǔ)在容器中。然而,如果虛擬機(jī)104指令指定在容器中存儲(chǔ)128位值類型,則容器對(duì)于容納值類型而言將不夠大。作為響應(yīng),虛擬機(jī)104會(huì)將容器重新分配為128位以便于存儲(chǔ)值類型。因此,存在與過大地設(shè)定被用于存儲(chǔ)局部變量401的容器的尺寸相關(guān)聯(lián)的存儲(chǔ)開銷以及與過小地設(shè)定容器的尺寸并且執(zhí)行頻繁的重新分配相關(guān)聯(lián)的處理開銷。

在一些實(shí)施例中,操作數(shù)棧402還被實(shí)現(xiàn)為存儲(chǔ)一個(gè)或多個(gè)容器的數(shù)據(jù)結(jié)構(gòu)。例如,操作數(shù)棧402可以被實(shí)現(xiàn)為存儲(chǔ)以先進(jìn)先出(FIFO)順序訪問的一個(gè)或多個(gè)容器的?;蚍侄蔚臈!R虼?,在一些實(shí)施例中,將值類型存儲(chǔ)到操作數(shù)棧中可以導(dǎo)致上面關(guān)于局部變量401所討論的相同問題。

在一些實(shí)施例中,虛擬機(jī)104實(shí)現(xiàn)分配規(guī)則和存儲(chǔ)優(yōu)化,該分配規(guī)則和存儲(chǔ)優(yōu)化降低了與在容器中存儲(chǔ)尺寸可變的值(諸如值類型)相關(guān)聯(lián)的開銷。

5.1存儲(chǔ)過程流

圖5示出了根據(jù)實(shí)施例的用于在容器中存儲(chǔ)值類型的過程。如上文所討論的,局部變量401和操作數(shù)棧402這二者都可以被實(shí)現(xiàn)為存儲(chǔ)容器的數(shù)據(jù)結(jié)構(gòu)。然而,圖5中示出的過程流對(duì)于被用于存儲(chǔ)容器的數(shù)據(jù)結(jié)構(gòu)是通用的。此外,圖5中框執(zhí)行的順序不是關(guān)鍵的。在其他實(shí)施例中,與圖5的圖示相比,框可以被重新排列、合并或者劃分為分開的框。下面的解釋假設(shè)圖5的過程流由虛擬機(jī)104的解釋器108執(zhí)行。另外,下面的解釋假設(shè)在圖5的過程期間幀400是當(dāng)前棧幀。

在框500處,解釋器108初始化一個(gè)或多個(gè)容器。在一些實(shí)施例中,當(dāng)響應(yīng)于方法調(diào)用而創(chuàng)建新的棧幀400時(shí)執(zhí)行框500。例如,該一個(gè)或多個(gè)容器可以表示用于存儲(chǔ)局部變量401的數(shù)據(jù)結(jié)構(gòu)和/或用于存儲(chǔ)操作數(shù)棧402的數(shù)據(jù)結(jié)構(gòu)。

在實(shí)施例中,解釋器108將所述一個(gè)或多個(gè)容器初始化為具有相同的固定尺寸。例如,解釋器108可以將容器初始化為存儲(chǔ)基本原生和/或引用所需要的尺寸。作為另一示例,解釋器108可以創(chuàng)建具有大于基本原生和/或引用的尺寸的固定尺寸的容器。

在一些實(shí)施例中,解釋器108將所述一個(gè)或多個(gè)容器初始化為可變的尺寸。例如,在一些實(shí)施例中,當(dāng)方法被調(diào)用時(shí),新的棧幀400被創(chuàng)建,前一個(gè)幀的操作數(shù)棧上的參數(shù)出棧并且被放置在新棧幀400的局部變量401中。因此,至少對(duì)于被用于存儲(chǔ)參數(shù)的容器而言,解釋器109可以將這些容器初始化為適合于方法調(diào)用所期待的參數(shù)類型(諸如原生類型、引用類型或值類型)的尺寸。例如,解釋器108可以通過檢查方法調(diào)用的描述符來確定參數(shù)類型。

然而,在一些實(shí)施例中,棧幀在存儲(chǔ)器中重疊以提升存儲(chǔ)效率。例如,調(diào)用者的棧幀可以與被調(diào)用者的棧幀在存儲(chǔ)器中重疊,使得調(diào)用者的操作數(shù)棧是與新棧幀的一個(gè)或多個(gè)局部變量相同的存儲(chǔ)器位置。在這樣的實(shí)施例中,當(dāng)調(diào)用者將這些值推到前一幀的操作數(shù)棧上時(shí),表示參數(shù)的局部變量401的容器被初始化。

在一些實(shí)施例中,解釋器108可能仍然需要用于在方法的主體內(nèi)聲明的變量(例如,無參數(shù)的局部變量)的容器。在一些實(shí)施例中,解釋器108預(yù)先分配若干容器以保持這種變量的值。然而,在其他實(shí)施例中,解釋器108延遲初始分配直至接收到將值存儲(chǔ)到局部變量中的指令。一旦接收到指令,則解釋器108分配對(duì)于存儲(chǔ)該值來說足夠大的容器。例如,容器可以通過編號(hào)(1、2、3、4等)索引,如果接收到在尚未被分配的容器的索引號(hào)處存儲(chǔ)值的指令,則解釋器108分配對(duì)于保持該值來說足夠大的容器。在一些實(shí)施例中,解釋器108修改用于保持容器的數(shù)據(jù)結(jié)構(gòu)的元數(shù)據(jù)和/或頭部信息以將索引號(hào)映射到容器。

在框501處,解釋器108接收在所分配的容器中存儲(chǔ)值類型的指令。在實(shí)施例中,作為逐句通過被調(diào)用的方法的代碼的結(jié)果,解釋器108接收指令。在框501處可以被解釋器108接收的指令示例包括vstore、vastore、vload、vaload和上文描述的用于值類型的其他指令。在一些實(shí)施例中,在框501處接收的指令表示“較高級(jí)別的”指令(諸如JVM字節(jié)碼),解釋器108的任務(wù)是將該“較高級(jí)別的”指令翻譯成一個(gè)或多個(gè)“較低級(jí)別的”指令,諸如被調(diào)整為適應(yīng)執(zhí)行虛擬機(jī)104的計(jì)算機(jī)系統(tǒng)的處理器的機(jī)器碼。

在框502處,解釋器108向驗(yàn)證器106饋送指令以針對(duì)一批規(guī)則進(jìn)行檢查。在一些實(shí)施例中,規(guī)則被設(shè)計(jì)為創(chuàng)建關(guān)于解釋器108的復(fù)制和/或重新分配努力的界限。在一些實(shí)施例中,當(dāng)驗(yàn)證器106檢測(cè)到規(guī)則被違背時(shí),驗(yàn)證器拋出異常,該異常由特殊的異常代碼來處理。

在實(shí)施例中,驗(yàn)證器106約束容器以在被分配為用于一個(gè)種類的值類型后僅保持該值類型。因此,如果容器被分配為保持特定尺寸的值類型,則驗(yàn)證器106阻止容器被用于可能具有不同尺寸要求的任何其他種類的值類型。結(jié)果,驗(yàn)證器106阻止解釋器108付出努力重新分配用于多個(gè)值類型的容器。然而,在一些實(shí)施例中,解釋器108允許容器被重新指派為其他值類型,假設(shè)該值類型有相同的尺寸(或者在一些實(shí)施例中,有較小的尺寸)。在一些實(shí)施例中,前面提到的約束被維持直至容器的類型被“重置”或者指派的值被移動(dòng)到其他地方。例如,“重置”指令可以重置類型和內(nèi)容,而“移動(dòng)”指令將重置類型以及將內(nèi)容重新指派到另一容器(諸如在操作數(shù)棧402的頂部上)。然而,對(duì)于不實(shí)現(xiàn)這種指令的實(shí)施例,一旦被設(shè)置,則對(duì)于方法調(diào)用的剩余部分,類型可以被永久指派到容器。

在框503處,解釋器108確定值類型是否適配所分配的容器。在實(shí)施例中,如果值類型具有與所分配的容器相同或者比分配的容器更小的尺寸,則解釋器108前進(jìn)到框504。否則,如果值類型比分配的容器的尺寸更大,則解釋器前進(jìn)到框505。

在框504處,解釋器108將值類型的內(nèi)容存儲(chǔ)到容器中。

在框505處,解釋器108確定值類型要通過引用還是通過值來存儲(chǔ)。在一些實(shí)施例中,解釋器108考慮各種因素來確定值類型要通過引用還是通過值來存儲(chǔ)在容器中。例如,因素可以包括容器的性質(zhì)、值類型的成分、較低級(jí)別的指令如何利用值類型、另一容器是否已經(jīng)存儲(chǔ)值類型等等。在一些實(shí)施例中,如果值類型大于閾值尺寸并且被確定為不可變,則解釋器108選擇通過引用來存儲(chǔ)值類型。因此,對(duì)于大的值類型,解釋器108可以選擇存儲(chǔ)對(duì)值類型的引用而不是復(fù)制值類型的內(nèi)容。結(jié)果,通過阻止重復(fù)復(fù)制尺寸過大的值類型可以實(shí)現(xiàn)存儲(chǔ)和處理高效率。然而,由于值類型被保證是不可變的,因此從用戶的視角來看,不存在副作用的風(fēng)險(xiǎn);原生值與值類型的處置之間不存在區(qū)別。如果解釋器108確定要通過值存儲(chǔ)值類型,則解釋器108前進(jìn)到框506。否則,如果解釋器108確定要通過引用存儲(chǔ)值類型,則解釋器108前進(jìn)到框507。

在框506處,解釋器108調(diào)整容器的尺寸。在一些實(shí)施例中,解釋器108通過對(duì)容器解除分配并且然后將容器重新分配為足以存儲(chǔ)值類型的尺寸來調(diào)整容器的尺寸。然而,在其他實(shí)施例中,取決于被用于存儲(chǔ)容器的數(shù)據(jù)結(jié)構(gòu),解釋器108可以被配置為在不執(zhí)行解除分配的情況下分配更多的存儲(chǔ)器以增加容器的尺寸。

在框507處,解釋器108在堆302上為值類型分配空間。在實(shí)施例中,解釋器108查找值類型的尺寸并且在堆302上分配對(duì)于存儲(chǔ)值類型來說足夠大的空間。然后解釋器108在分配的空間處在堆302上存儲(chǔ)值類型。

在框508處,解釋器108在容器中存儲(chǔ)對(duì)值類型的引用。在實(shí)施例中,在框507處解釋器108存儲(chǔ)對(duì)在堆302上為值類型分配的空間的引用。

在一些實(shí)施例中,在框505處的確定中,因素是另一容器是否已經(jīng)存儲(chǔ)用于值類型的值的拷貝。在這種情況中,如果解釋器108確定將值類型存儲(chǔ)為引用,而不是在堆302上存儲(chǔ)值類型并且在容器中存儲(chǔ)對(duì)堆302的引用,則解釋器108在容器中存儲(chǔ)對(duì)存儲(chǔ)值類型的其他容器的引用。例如,并非將來自局部變量的值類型復(fù)制到操作數(shù)棧402,解釋器108可以替代地復(fù)制對(duì)存儲(chǔ)用于該局部變量的值類型的容器的引用。作為另一示例,并非將來自局部變量的值復(fù)制到另一局部變量,解釋器108可以替代地復(fù)制對(duì)存儲(chǔ)第二個(gè)局部變量的值的容器的引用。在一些實(shí)施例中,僅當(dāng)容器中的值不可變時(shí)才執(zhí)行前面提到的優(yōu)化,以防止副作用。

6.0原子操作

在一些實(shí)施例中,虛擬機(jī)104被配置為允許值類型或值類型的選定字段被原子地訪問。因此,向虛擬機(jī)104中的每個(gè)運(yùn)行的線程提供值類型(或選定字段)的一致視圖。例如,值類型可以是具有由用戶定義的多個(gè)成分的復(fù)合。取決于虛擬機(jī)104運(yùn)行在其上的硬件,處理器的指令集可能不具有支持一次更新整個(gè)值類型的指令。作為示例,當(dāng)構(gòu)造函數(shù)為一個(gè)線程構(gòu)造值類型時(shí),另一個(gè)線程可能看到該值類型的不一致的視圖,其中僅僅值類型的一部分已經(jīng)更新。許多類型的硬件提供了用于執(zhí)行原子操作的機(jī)制,但是這些機(jī)制具有不同程度的開銷。此外,在一些情況中,硬件機(jī)制可能是不夠的;這使得經(jīng)常發(fā)生的由軟件實(shí)現(xiàn)的鎖定方案具有非常高的開銷。因此,在一些實(shí)施例中,語(yǔ)言允許值類型被加標(biāo)志以用于在諸如整個(gè)值類型、值類型中的選定字段或者訪問值類型的獨(dú)個(gè)指令之類的不同粒度級(jí)別的原子訪問。

在一些實(shí)施例中,僅當(dāng)值類型被存儲(chǔ)在堆302上時(shí)遇到競(jìng)爭(zhēng)狀況和原子性的問題。這是因?yàn)樵谝恍?shí)施例中堆302存儲(chǔ)在線程之間共享的數(shù)據(jù),但是線程區(qū)域307(包括虛擬機(jī)棧)存儲(chǔ)僅能被獨(dú)個(gè)線程訪問的數(shù)據(jù)。因此,(通過值)存儲(chǔ)在棧幀400中的值類型不經(jīng)歷競(jìng)爭(zhēng)狀況,因?yàn)閮H一個(gè)線程將訪問這些值類型。然而,當(dāng)值類型例如作為封裝對(duì)象的字段被存儲(chǔ)在堆302上時(shí),多個(gè)線程可以潛在地讀取該值,從而導(dǎo)致競(jìng)爭(zhēng)狀況。

圖6示出了根據(jù)實(shí)施例的用于訪問值類型的過程流。為了示出清楚的示例,將從虛擬機(jī)104的解釋器108的視角來說明圖6的過程流。

在框600處,解釋器108接收訪問存儲(chǔ)在容器中的值類型的字段的指令。在一些實(shí)施例中,解釋器108接收從值類型的字段加載值或?qū)⒅荡鎯?chǔ)到值類型的字段的指令。例如,上文描述的vgetfield和vputfield指令是在框600處可以接收的指令的示例。

在框601處,解釋器108確定字段是否要被原子地對(duì)待。如果是,則解釋器108前進(jìn)到框602。否則,解釋器108前進(jìn)到框602。在實(shí)施例中,響應(yīng)于檢測(cè)到以下情況中之一,解釋器108確定字段是原子的:值類型已經(jīng)被標(biāo)記為始終是原子的,值類型的字段已經(jīng)被單獨(dú)地標(biāo)記為用于原子訪問,或者指令被標(biāo)記為是原子指令。例如,在源代碼文件101中,值類型的聲明、值類型的字段或使用值類型的指令包括諸如“atomic(原子的)”或“always atomic(始終是原子的)”之類的關(guān)鍵字。當(dāng)編譯器102編譯源代碼文件101時(shí),利用指示這些成分要被原子地對(duì)待的標(biāo)志或元數(shù)據(jù)來標(biāo)記類文件103。然后解釋器108可以讀取這些類文件103(或者加載到虛擬機(jī)存儲(chǔ)器布局300中的類文件103的表示)以確定字段是否要被原子地對(duì)待。

在框602處,解釋器108在沒有原子限制的情況下執(zhí)行訪問。例如,解釋器108可以通過將訪問轉(zhuǎn)換為不提供任何原子保證的較低級(jí)別的指令而在沒有原子限制的情況下執(zhí)行訪問。

在框603處,解釋器108確定字段是否是不可變的。在一些實(shí)施例中,字段或值類型作為整體與源代碼文件101中指示字段或值類型被凍結(jié)并且不能改變的關(guān)鍵字相關(guān)聯(lián)。類似于上文描述的“atomic”關(guān)鍵字,這可以作為標(biāo)志或元數(shù)據(jù)被反映在類文件103和/或虛擬機(jī)存儲(chǔ)器布局300中以供解釋器108在框603期間讀取。如果字段是不可變的,則解釋器108前進(jìn)到框602。如果字段是可變的,則解釋器108前進(jìn)到框604。

在框604處,解釋器108確定字段是否被頻繁訪問。在一些實(shí)施例中,解釋器108跟蹤在每次訪問期間遞增的與值類型的字段或值類型本身相關(guān)聯(lián)的元數(shù)據(jù)。如果元數(shù)據(jù)指示訪問的數(shù)量超過了特定閾值,則解釋器108確定該字段被頻繁訪問。然而,在其他實(shí)施例中,還考慮時(shí)間分量,諸如追蹤在時(shí)間的某個(gè)表示(真實(shí)時(shí)間、計(jì)算機(jī)時(shí)間、所執(zhí)行的指令的數(shù)量等等)內(nèi)訪問的數(shù)量。如果解釋器108確定字段被頻繁訪問,則解釋器108前進(jìn)到框605。如果解釋器108確定字段不被頻繁訪問,則解釋器108前進(jìn)到框606。

在框605處,解釋器108在分開的容器中存儲(chǔ)字段。在一些實(shí)施例中,解釋器108將字段從扁平化的形式改變?yōu)橐帽硎?。與扁平化的值相比,對(duì)于原子地訪問來說引用通常更快。例如,對(duì)于放置/存儲(chǔ)指令,字段的新值可以在堆302上創(chuàng)建并且可以通過更新對(duì)新存儲(chǔ)器位置的引用來原子地更新字段。此外,對(duì)于原子的加載,只要字段經(jīng)由指針更新,則被加載的值要么表示整個(gè)新值要么表示整個(gè)舊值,而不可能保留部分更新的值。因此,可以避免諸如鎖定之類的需要顯著開銷的原子技術(shù)。

在框606處,解釋器108原子地執(zhí)行訪問。在實(shí)施例中,解釋器108在框606處從多個(gè)技術(shù)中選擇對(duì)于當(dāng)前環(huán)境而言最高效的特定技術(shù)。例如,執(zhí)行虛擬機(jī)104的硬件可以支持可被用于原子地執(zhí)行訪問的事務(wù)或者其他基于硬件的原子指令。然而,在一些情況中,硬件可能不支持足以執(zhí)行訪問的原子指令,因此在這種情況下解釋器108回退到基于軟件的原子技術(shù),諸如執(zhí)行鎖定。在實(shí)施例中,只要可能,相比于基于軟件的技術(shù),解釋器108優(yōu)選基于硬件的原子指令。然而,在其他實(shí)施例中,解釋器108能夠訪問指示技術(shù)的排名的元數(shù)據(jù)。例如,當(dāng)程序運(yùn)行時(shí),解釋器108可以嘗試各種類型的原子訪問技術(shù)并且基于速度將這些技術(shù)排名。

7.0硬件概述

根據(jù)一個(gè)實(shí)施例,本文描述的技術(shù)由一個(gè)或多個(gè)專用計(jì)算設(shè)備實(shí)現(xiàn)。專用計(jì)算設(shè)備可以被硬連線以執(zhí)行所述技術(shù),或者可以包括被永久編程為執(zhí)行所述技術(shù)的諸如一個(gè)或多個(gè)專用集成電路(ASIC)或現(xiàn)場(chǎng)可編程門陣列(FPGA)之類的數(shù)字電子設(shè)備,或者可以包括被編程為根據(jù)固件、存儲(chǔ)器、其他存儲(chǔ)設(shè)備或者組合中的程序指令來執(zhí)行所述技術(shù)的一個(gè)或多個(gè)通用硬件處理器。這種專用計(jì)算設(shè)備還可以將定制的硬連線邏輯、ASIC或FPGA與定制的編程相組合以實(shí)現(xiàn)所述技術(shù)。專用計(jì)算設(shè)備可以是含有用于實(shí)現(xiàn)所述技術(shù)的硬連線邏輯和/或程序邏輯的桌上型計(jì)算機(jī)系統(tǒng)、便攜式計(jì)算機(jī)系統(tǒng)、手持設(shè)備、聯(lián)網(wǎng)絡(luò)設(shè)備或任何其他設(shè)備。

例如,圖7是示出在其上可以實(shí)現(xiàn)本發(fā)明的實(shí)施例的計(jì)算機(jī)系統(tǒng)700的框圖。計(jì)算機(jī)系統(tǒng)700包括用于傳送信息的總線702或其他通信機(jī)構(gòu),以及用于處理信息的、與總線702耦接的硬件處理器704。硬件處理器704可以是例如通用微處理器。

計(jì)算機(jī)系統(tǒng)700還包括用于存儲(chǔ)信息和要由處理器704執(zhí)行的指令的、耦接到總線702的主存儲(chǔ)器706(諸如隨機(jī)存取存儲(chǔ)器(RAM))或其他動(dòng)態(tài)存儲(chǔ)設(shè)備。主存儲(chǔ)器706還可以被用于在要由處理器704執(zhí)行的指令的執(zhí)行期間存儲(chǔ)臨時(shí)變量或其他中間信息。這種指令當(dāng)被存儲(chǔ)在處理器704可訪問的非暫態(tài)存儲(chǔ)介質(zhì)中時(shí),使計(jì)算機(jī)系統(tǒng)700成為被定制為執(zhí)行指令中指定的操作的專用機(jī)器。

計(jì)算機(jī)系統(tǒng)700還包括存儲(chǔ)用于處理器704的靜態(tài)信息和指令的、耦接到總線702的只讀存儲(chǔ)器(ROM)708或其他靜態(tài)存儲(chǔ)設(shè)備。諸如磁盤、光盤或固態(tài)驅(qū)動(dòng)器之類的存儲(chǔ)設(shè)備710被提供并且被耦接到總線702以用于存儲(chǔ)信息和指令。

計(jì)算機(jī)系統(tǒng)700可以經(jīng)由總線702耦接到諸如發(fā)光二極管(LED)顯示器之類的顯示器712以用于向計(jì)算機(jī)用戶顯示信息。包括字母數(shù)字鍵和其他鍵的輸入設(shè)備714被耦接到總線702以用于向處理器704傳送信息和命令選擇。另一種類型的用戶輸入設(shè)備是用于向處理器704傳送方向信息和命令選擇以及用于控制顯示器712上的光標(biāo)移動(dòng)的光標(biāo)控制器716,諸如鼠標(biāo)、跟蹤球或光標(biāo)方向鍵。該輸入設(shè)備典型地具有允許設(shè)備在平面上指定位置的在第一軸(例如,x)和第二軸(例如,y)這兩個(gè)軸上的兩個(gè)自由度。

計(jì)算機(jī)系統(tǒng)700可以通過使用與計(jì)算機(jī)系統(tǒng)結(jié)合使得計(jì)算機(jī)系統(tǒng)700成為專用機(jī)器或者將計(jì)算機(jī)系統(tǒng)700編程為專用機(jī)器的定制的硬連線邏輯、一個(gè)或多個(gè)ASIC或FPGA、固件和/或程序邏輯來實(shí)現(xiàn)本文描述的技術(shù)。根據(jù)一個(gè)實(shí)施例,本文的技術(shù)由計(jì)算機(jī)系統(tǒng)700響應(yīng)于處理器704執(zhí)行包含在主存儲(chǔ)器706中的一個(gè)或多個(gè)指令的一個(gè)或多個(gè)序列來執(zhí)行。這種指令可以從諸如存儲(chǔ)設(shè)備710之類的另一個(gè)存儲(chǔ)介質(zhì)讀取到主存儲(chǔ)器706中。包含在主存儲(chǔ)器706中的指令序列的執(zhí)行使得處理器704執(zhí)行本文所描述的過程步驟。在可替代的實(shí)施例中,硬連線電路可以代替軟件指令使用或與軟件指令結(jié)合使用。

如在此所使用的術(shù)語(yǔ)“存儲(chǔ)介質(zhì)”是指存儲(chǔ)使得機(jī)器以特定方式操作的數(shù)據(jù)和/或指令的任何非暫態(tài)介質(zhì)。這種存儲(chǔ)介質(zhì)可以包括非易失性介質(zhì)和/或易失性介質(zhì)。非易失性介質(zhì)例如包括光盤、磁盤或固態(tài)驅(qū)動(dòng)器,諸如存儲(chǔ)設(shè)備710。易失性介質(zhì)包括動(dòng)態(tài)存儲(chǔ)器,諸如主存儲(chǔ)器706。常見形式的存儲(chǔ)介質(zhì)例如包括軟盤、柔性盤、硬盤、固態(tài)驅(qū)動(dòng)器、磁帶或任何其他磁數(shù)據(jù)存儲(chǔ)介質(zhì)、CD-ROM、任何其他光學(xué)數(shù)據(jù)存儲(chǔ)介質(zhì)、具有孔圖案的任何物理介質(zhì)、RAM、PROM和EPROM、FLASH-EPROM、NVRAM、任何其他存儲(chǔ)器芯片或盒。

存儲(chǔ)介質(zhì)不同于傳輸介質(zhì),但是可以與傳輸介質(zhì)結(jié)合使用。傳輸介質(zhì)參與在存儲(chǔ)介質(zhì)之間傳送信息。例如,傳輸介質(zhì)包括同軸線纜、銅線和光纖,包括包含總線402的線。傳輸介質(zhì)還可以采取聲波或光波的形式,諸如在無線電波和紅外數(shù)據(jù)通信期間生成的聲波或光波。

各種形式的介質(zhì)可以涉及將一個(gè)或多個(gè)指令的一個(gè)或多個(gè)序列承載到處理器704以供執(zhí)行。例如,指令可以初始地被承載在遠(yuǎn)程計(jì)算機(jī)的磁盤或固態(tài)驅(qū)動(dòng)器上。遠(yuǎn)程計(jì)算機(jī)可以將指令加載到它的動(dòng)態(tài)存儲(chǔ)器中并且使用調(diào)制解調(diào)器通過電話線發(fā)送指令。計(jì)算機(jī)系統(tǒng)700的本地調(diào)制解調(diào)器可以接收電話線上的數(shù)據(jù)并且使用紅外傳輸器將數(shù)據(jù)轉(zhuǎn)換成紅外信號(hào)。紅外檢測(cè)器可以接收紅外信號(hào)中承載的數(shù)據(jù),并且合適的電路可以將數(shù)據(jù)放置在總線702上。總線702將數(shù)據(jù)承載到主存儲(chǔ)器706,處理器704從主存儲(chǔ)器706檢索指令并且執(zhí)行指令。由主存儲(chǔ)器706接收的指令可以選擇性地在被處理器704執(zhí)行之前或之后存儲(chǔ)在存儲(chǔ)設(shè)備710上。

計(jì)算機(jī)系統(tǒng)700還包括耦接到總線702的通信接口718。通信接口718提供耦接到網(wǎng)絡(luò)鏈路720的雙向數(shù)據(jù)通信,網(wǎng)絡(luò)鏈路720被連接到本地網(wǎng)絡(luò)722。例如,通信接口718可以是綜合業(yè)務(wù)數(shù)字網(wǎng)(ISDN)卡、線纜調(diào)制解調(diào)器、衛(wèi)星調(diào)制解調(diào)器或者用于提供到對(duì)應(yīng)類型的電話線的數(shù)據(jù)通信連接的調(diào)制解調(diào)器。作為另一示例,通信接口718可以是局域網(wǎng)(LAN)卡以提供到兼容的LAN的數(shù)據(jù)通信連接。無線鏈路也可以被實(shí)現(xiàn)。在任何這種實(shí)施方式中,通信接口718發(fā)送和接收承載有表示各種類型的信息的數(shù)字?jǐn)?shù)據(jù)流的電信號(hào)、電磁信號(hào)或光信號(hào)。

網(wǎng)絡(luò)鏈路720典型地通過一個(gè)或多個(gè)網(wǎng)絡(luò)提供到其他數(shù)據(jù)設(shè)備的數(shù)據(jù)通信。例如,網(wǎng)絡(luò)鏈路720可以通過本地網(wǎng)絡(luò)722提供到主機(jī)計(jì)算機(jī)724或到由網(wǎng)絡(luò)服務(wù)提供商(ISP)726運(yùn)營(yíng)的數(shù)據(jù)裝置的連接。ISP 726又通過現(xiàn)在通常被稱為“互聯(lián)網(wǎng)”728的全球分組數(shù)據(jù)通信網(wǎng)提供數(shù)據(jù)通信服務(wù)。本地網(wǎng)絡(luò)722和因特網(wǎng)728都使用承載有數(shù)字?jǐn)?shù)據(jù)流的電信號(hào)、電磁信號(hào)或光信號(hào)。通過各種網(wǎng)絡(luò)的信號(hào)和在網(wǎng)絡(luò)鏈路720上并通過通信接口718的信號(hào)是傳輸介質(zhì)的示例形式,這些信號(hào)承載有到計(jì)算機(jī)系統(tǒng)700的數(shù)字?jǐn)?shù)據(jù)以及來自計(jì)算機(jī)系統(tǒng)700的數(shù)字?jǐn)?shù)據(jù)。

計(jì)算機(jī)系統(tǒng)700可以通過網(wǎng)絡(luò)、網(wǎng)絡(luò)鏈路720和通信接口718來發(fā)送消息和接收包括程序代碼的數(shù)據(jù)。在互聯(lián)網(wǎng)示例中,服務(wù)器730可以通過互聯(lián)網(wǎng)728、ISP 726、本地網(wǎng)絡(luò)722和通信接口718來傳送用于應(yīng)用程序的請(qǐng)求的代碼。

所接收的代碼可以如它被接收的那樣由處理器704執(zhí)行,和/或被存儲(chǔ)在存儲(chǔ)設(shè)備710或者其他非易失性存儲(chǔ)中以便以后執(zhí)行。

如本文所使用的,術(shù)語(yǔ)“一個(gè)”、“兩個(gè)”、“某個(gè)”和“特定”被用作命名約定以將查詢、計(jì)劃、表示、步驟、對(duì)象、設(shè)備或其他項(xiàng)彼此區(qū)分開,以使得這些項(xiàng)可以在它們被介紹之后被引用。除非在此另外指定,這些術(shù)語(yǔ)的使用不暗示所引用的項(xiàng)的順序、時(shí)序或任何其他特性。

8.0擴(kuò)展和替代

在上面的說明書中,已經(jīng)參照隨著實(shí)施方式不同而不同的許多具體細(xì)節(jié)描述了本發(fā)明的實(shí)施例。因此,本發(fā)明是什么以及申請(qǐng)人意圖本發(fā)明是什么的唯一且排他的指示物是以權(quán)利要求發(fā)布的具體形式從本申請(qǐng)中發(fā)布的一組權(quán)利要求,包括任何后續(xù)補(bǔ)正。針對(duì)權(quán)利要求中所包含的術(shù)語(yǔ),本文明確闡述的任何定義應(yīng)當(dāng)決定如權(quán)利要求中使用的這些術(shù)語(yǔ)的含義。因此,在權(quán)利要求中沒有明確表述的限制、要素、性質(zhì)、特征、優(yōu)點(diǎn)或?qū)傩远疾粦?yīng)當(dāng)以任何方式限制這些權(quán)利要求的范圍。因此,說明書和附圖應(yīng)被視為是說明性的而非限制性的。

9.0第一附加公開

本文所描述的主題的方面列舉在以下標(biāo)號(hào)的條款中:

1.一種方法,包括:接收指定將特定值類型的值指派到多個(gè)容器中的特定容器的一個(gè)或多個(gè)較高級(jí)別的指令,其中所述多個(gè)容器表示用于在代碼塊的執(zhí)行期間維護(hù)一個(gè)或多個(gè)變量的數(shù)據(jù)結(jié)構(gòu),其中所述多個(gè)容器中的至少兩個(gè)容器具有不同的尺寸;基于根據(jù)所述特定值類型將一個(gè)或多個(gè)指派規(guī)則應(yīng)用于所述一個(gè)或多個(gè)較高級(jí)別的指令,生成將所述值指派到所述特定容器的一個(gè)或多個(gè)較低級(jí)別的指令;執(zhí)行所述一個(gè)或多個(gè)較低級(jí)別的指令;其中所述方法由一個(gè)或多個(gè)計(jì)算設(shè)備執(zhí)行。

2.如條款1所述的方法,其中所述一個(gè)或多個(gè)指派規(guī)則包括以下中的一個(gè)或多個(gè):限制哪些值類型能夠被指派到所述特定容器的約束,在向所述特定容器中加載所述值的拆箱表示或?qū)Ρ3炙鲋档牡诙萜鞯囊弥g進(jìn)行選擇的規(guī)則。

3.如條款2所述的方法,其中在向特定容器中加載所述值的所述拆箱表示或?qū)Ρ3炙鲋档牡诙萜鞯囊弥g進(jìn)行選擇的規(guī)則基于以下中的一項(xiàng)或多項(xiàng):所述值是否是不可變的、所述值是否能夠適配在所述特定容器內(nèi)、所述值是否超出了特定的尺寸閾值、所述多個(gè)容器中的另一個(gè)容器是否已經(jīng)存儲(chǔ)了所述值、所述值的成分的性質(zhì)、或者所述一個(gè)或多個(gè)較低級(jí)別的指令將如何利用所述值。

4.如條款2-3中的任一項(xiàng)所述的方法,其中所述多個(gè)容器被存儲(chǔ)在為多個(gè)線程中的特定線程預(yù)留的存儲(chǔ)器位置中,并且所述第二容器在由所述多個(gè)線程共享的存儲(chǔ)器位置中位于所述多個(gè)容器的外部。

5.如條款2-4中的任一項(xiàng)所述的方法,其中所述約束基于以下中的一項(xiàng)或多項(xiàng):(1)確定所述特定容器已經(jīng)被分配為適配一個(gè)或多個(gè)值類型,并且將對(duì)所述特定容器的指派限制為所述一個(gè)或多個(gè)值類型的值,(2)將對(duì)所述特定容器的指派限制為與所述特定容器共享尺寸的值或具有比所述特定容器小的尺寸的值,(3)將對(duì)所述特定容器的指派限制為一個(gè)或多個(gè)特定值類型直至接收到重置所述特定容器的指令。

6.如條款2-5中的任一項(xiàng)所述的方法,還包括:響應(yīng)于確定要在所述特定容器中加載所述值的所述拆箱表示以及確定所述特定容器不能適配所述值,調(diào)整所述特定容器的尺寸以適配所述值。

7.如條款1-6中的任一項(xiàng)所述的方法,還包括:接收指定改變第二特定容器中存儲(chǔ)的第二值的成分的一個(gè)或多個(gè)第二較高級(jí)別的指令,其中所述第二值具有第二特定值類型;至少部分地基于與所述第二特定值類型相關(guān)聯(lián)的元數(shù)據(jù)來生成識(shí)別所述第二特定容器的與所述成分部分對(duì)應(yīng)的部分的單個(gè)較低級(jí)別的指令;執(zhí)行所述單個(gè)較低級(jí)別的指令。

8.如條款2-7中的任一項(xiàng)所述的方法,其中識(shí)別所述第二特定容器的所述部分包括以下中的一項(xiàng)或多項(xiàng):使用對(duì)應(yīng)于所述第二特定值類型的值類型定義的字段定義來定位所述部分,使用所述值類型定義的訪問控制信息來實(shí)行對(duì)所述部分的訪問限制,或者基于所述值類型定義來執(zhí)行類型檢查。

9.如條款1-8中的任一項(xiàng)所述的方法,還包括:接收指定訪問第二特定容器中存儲(chǔ)的第二值的成分的一個(gè)或多個(gè)第二較高級(jí)別的指令,其中所述第二值具有第二特定值類型;基于與所述第二特定值類型相關(guān)聯(lián)的元數(shù)據(jù)來確定對(duì)所述成分的訪問是否應(yīng)當(dāng)是原子的;響應(yīng)于確定對(duì)所述成分的訪問應(yīng)當(dāng)是原子的,確定所述成分是否存儲(chǔ)在不可變?nèi)萜髦校豁憫?yīng)于確定所述成分存儲(chǔ)在不可變?nèi)萜髦?,生成不提供原子保證的一個(gè)或多個(gè)第二較低級(jí)別的指令并且執(zhí)行所述一個(gè)或多個(gè)第二較低級(jí)別的指令;響應(yīng)于確定所述成分沒有存儲(chǔ)在不可變?nèi)萜髦校x擇能夠提供對(duì)所述成分的原子訪問的一個(gè)或多個(gè)機(jī)制中的特定機(jī)制,基于所述特定機(jī)制生成提供原子保證的一個(gè)或多個(gè)第三較低級(jí)別的指令,以及執(zhí)行所述一個(gè)或多個(gè)第三較低級(jí)別的指令。

10.如條款2-9中的任一項(xiàng)所述的方法,其中所述第二值存儲(chǔ)在第一容器中,并且所述方法還包括:響應(yīng)于確定所述成分沒有存儲(chǔ)在不可變?nèi)萜髦?,確定所述成分的訪問頻率是否超過訪問閾值;響應(yīng)于確定所述成分的所述訪問頻率超過所述訪問閾值,將所述成分存儲(chǔ)在分開的第二容器中并且針對(duì)所述成分在所述第一容器中存儲(chǔ)對(duì)所述第二容器的引用。

11.如條款2-10中的任一項(xiàng)所述的方法,其中能夠提供對(duì)所述成分的原子訪問的所述一個(gè)或多個(gè)機(jī)制基于由所述一個(gè)或多個(gè)計(jì)算設(shè)備的一個(gè)或多個(gè)處理器支持的一組指令。

12.存儲(chǔ)有指令的一個(gè)或多個(gè)計(jì)算機(jī)可讀介質(zhì),所述指令當(dāng)被一個(gè)或多個(gè)計(jì)算設(shè)備執(zhí)行時(shí)使得執(zhí)行如條款1-11中的任一項(xiàng)所述的步驟。

13.一種系統(tǒng),該系統(tǒng)包括一個(gè)或多個(gè)計(jì)算設(shè)備,所述一個(gè)或多個(gè)計(jì)算設(shè)備包括至少部分地由計(jì)算硬件實(shí)現(xiàn)的、被配置為實(shí)現(xiàn)如條款1-11中的任一項(xiàng)所述的步驟。

10.0第二附加公開

根據(jù)實(shí)施例,諸如當(dāng)將Java或其他源代碼編譯為字節(jié)碼或在任何其他合適的編程環(huán)境中時(shí),根據(jù)較高級(jí)別的指令生成較低級(jí)別的指令。較低級(jí)別的指令包括訪問諸如運(yùn)行時(shí)數(shù)據(jù)區(qū)域的局部變量、棧元素、寄存器、虛擬寄存器和/或其他命名的虛擬變量的之類的容器內(nèi)的值的指令。容器具有變化的尺寸以便于例如能夠直接地而不是通過對(duì)堆或其他存儲(chǔ)器區(qū)域中的容器的引用來存儲(chǔ)具有可變尺寸的值。

較高級(jí)別的指令包括某個(gè)值類型的值。值可以是例如由若干成分組成的非原生的復(fù)合值,諸如Point或Complex。該某個(gè)值類型可以例如由類定義,其中該類的值是實(shí)例。響應(yīng)于較高級(jí)別的指令,較低級(jí)別的指令可以被生成以將值或者(在一些情況中)對(duì)值的引用加載到尺寸可變化的容器之一。這種較低級(jí)別的指令的一個(gè)示例是本文所描述的vaload指令。或者,較低級(jí)別的指令可以存儲(chǔ)、修改、移動(dòng)和/或重置容器。在任何一種情況中,基于特定值類型以及基于與特定值類型相關(guān)的一個(gè)或多個(gè)指派規(guī)則來生成較低級(jí)別的指令。這種指派規(guī)則可以被配置為例如限制與維護(hù)支持可變尺寸的容器而非具有預(yù)定義的固定尺寸的容器相關(guān)聯(lián)的成本,和/或限制維護(hù)在容器之間復(fù)制的值的多個(gè)拷貝的成本。

在實(shí)施例中,指派規(guī)則可以包括例如一個(gè)或多個(gè)約束,在該一個(gè)或多個(gè)約束下,在方法的調(diào)用期間,不同的值類型可以被加載到容器中。在實(shí)施例中,這種約束的一個(gè)示例可以指定在方法的過程期間被加載到容器中的值可以具有最多一種數(shù)據(jù)類型或者數(shù)據(jù)類型的有限集合。因此,給定的容器可以僅保持容器最初被分配的值類型的值以及選擇地保持原生或引用的值。選擇性地,該約束可以持續(xù)至容器的類型被重置或者被指派的值被移動(dòng)到其他地方為止。例如,“重置”指令將重置類型以及內(nèi)容,而“移動(dòng)”指令將重置類型以及將內(nèi)容重新指派到另一個(gè)容器,諸如棧的頂部。移動(dòng)操作將線性類型或所有權(quán)(ownership)類型的概念應(yīng)用于解釋器效率。

在實(shí)施例中,另一示例性約束可以是被指派到容器的值必須全部具有如下值類型:該值類型被保證具有不大于指定尺寸的尺寸或者可替代地被保證具有與指定尺寸完全相同的尺寸。在實(shí)施例中,另一示例性約束可以是在方法的過程期間被記載到給定容器的值可以具有變化的數(shù)據(jù)類型,但是如果給定容器被用于存儲(chǔ)值類型,則它不能被用于存儲(chǔ)不同的類型(可選擇地,直至容器被重置)。

在實(shí)施例中,指派規(guī)則的另一示例是在將值的拆箱表示或者對(duì)保持值的外部容器的引用加載到容器中之間最優(yōu)地選擇的規(guī)則。這種規(guī)則可以考慮諸如外部容器或值的成分的性質(zhì)或較低級(jí)別的指令內(nèi)如何利用值之類的因素。例如,規(guī)則可以基于值在外部容器內(nèi)是否有效地是不可變的。在實(shí)施例中,指派規(guī)則的另一示例是關(guān)于當(dāng)?shù)诙萜饕呀?jīng)包含第一容器的值的拷貝時(shí)將值加載到第一容器中的約束。任何其他合適的指派規(guī)則也可以同時(shí)或者替代地被利用。

根據(jù)實(shí)施例,在一組指令的驗(yàn)證(諸如在解釋器解釋字節(jié)碼之前由字節(jié)碼驗(yàn)證器進(jìn)行的驗(yàn)證)期間執(zhí)行某些步驟。例如,當(dāng)驗(yàn)證根據(jù)上文所描述的技術(shù)生成的較低級(jí)別的指令時(shí),步驟可以被執(zhí)行。所述步驟包括識(shí)別將值加載到具有變化的尺寸的一組容器中的容器的指令。步驟還包括基于要被加載在容器中的值的值類型來驗(yàn)證指令遵從一個(gè)或多個(gè)約束。在實(shí)施例中,約束可以包括上文所描述的指派規(guī)則和/或約束中的一個(gè)或多個(gè)。

根據(jù)實(shí)施例,當(dāng)從較高級(jí)別的指令生成較低級(jí)別的指令時(shí),改變某個(gè)值類型的值內(nèi)的字段的一個(gè)或多個(gè)較高級(jí)別的指令可被識(shí)別。值可以是例如潛在地具有多個(gè)不同成分字段的值類型的實(shí)例。本文描述了這種值類型的示例,諸如Point或Complex??梢源_定的是,在較低級(jí)別的指令的背景下,用于值的至少一個(gè)成分字段的數(shù)據(jù)將被集體存儲(chǔ)在單個(gè)容器內(nèi)。例如,字段可以被存儲(chǔ)為其對(duì)應(yīng)的子值的拆箱表示,而不是對(duì)存儲(chǔ)對(duì)應(yīng)的子值的其他容器的引用。響應(yīng)于該確定,單個(gè)較低級(jí)別的指令被生成。這種較低級(jí)別的指令的示例是本文所描述的vput指令。

所生成的單個(gè)較低級(jí)別的指令被配置為命令解釋器識(shí)別容器的對(duì)應(yīng)于字段的部分,諸如一個(gè)或多個(gè)位。單個(gè)較低級(jí)別的指令還被配置為命令解釋器根據(jù)一個(gè)或多個(gè)較高級(jí)別的指令改變?cè)摬糠?。識(shí)別和/或改變可以至少部分基于與值的值類型相關(guān)聯(lián)的元數(shù)據(jù)。例如,指令可以使得解釋器使用值類型的字段定義來定位該部分,和/或?qū)嵭杏糜趯?duì)應(yīng)的值類型定義的訪問控制信息和類型檢查等。在實(shí)施例中,單個(gè)較低級(jí)別的指令命令解釋器在不使用指針來定位字段和/或不必發(fā)出打開值進(jìn)入到其成分字段中的另一命令的情況下來執(zhí)行這些操作。

在實(shí)施例中,通過重新排序、合并或分開與彼此相關(guān)并且與可以讀取或?qū)懭氪鎯?chǔ)在容器中的值或該值的至少一些成分字段的任何其他指令相關(guān)的兩個(gè)或更多個(gè)這種較低級(jí)別的指令的效果,選擇地生成較低級(jí)別的指令。這種效果的重新排序、合并或分開可以經(jīng)受保護(hù)存儲(chǔ)在容器中的值的每個(gè)成分字段以及作為整體存儲(chǔ)在容器中的值的一致性的規(guī)則。因此,技術(shù)可以包括使用分層的數(shù)據(jù)結(jié)構(gòu)的嵌套存儲(chǔ)器模型,當(dāng)對(duì)象拆分成值時(shí),該數(shù)據(jù)結(jié)構(gòu)可以拆分成更小的值并且最終一直向下拆分成成分原生和引用。

根據(jù)實(shí)施例,方法包括:當(dāng)解釋諸如Java字節(jié)碼之類的指令時(shí),識(shí)別用于插入較小的第一值作為較大的第二值的字段的指令。該指令可以是例如單個(gè)較低級(jí)別的指令,諸如上面生成的指令。第二值可以是例如具有被集體存儲(chǔ)在容器中的多個(gè)不同成分字段的經(jīng)定義的值類型的值。第一值可以是例如對(duì)應(yīng)于字段的子值。在實(shí)施例中,確定第二值具有某個(gè)值類型?;谂c某個(gè)值類型相關(guān)聯(lián)的元數(shù)據(jù),對(duì)應(yīng)于字段的第二值的一部分被定位,并且第一值被加載到該部分中。這可以包括例如基于與某個(gè)值類型相關(guān)聯(lián)的值類型定義數(shù)據(jù)來實(shí)行訪問控制信息和類型檢查,和/或使用值類型定義數(shù)據(jù)來定位相關(guān)部分。在實(shí)施例中,通過重新排序、合并或分開兩個(gè)或更多個(gè)這種較低級(jí)別的指令的效果來選擇性生成較低級(jí)別的指令,諸如上文所描述的。

根據(jù)實(shí)施例,代碼可以訪問意欲是原子的值的字段。這種代碼可以包括例如諸如getfield或putfield之類的指令。由于例如其值是實(shí)例的值類型的定義中的聲明、或者當(dāng)值被實(shí)例化時(shí)的聲明、和/或解釋器或編譯器的默認(rèn)配置,值可以是原子的。響應(yīng)于該代碼,編譯器或解釋器可以做出與決定在訪問字段時(shí)是否實(shí)現(xiàn)鎖定策略和/或?qū)崿F(xiàn)哪個(gè)鎖定策略相關(guān)的一個(gè)或多個(gè)確定。

在實(shí)施例中,一種這樣的確定是字段是否為不可變的。例如,字段可以被局限于正在執(zhí)行的線程,字段可以是“凍結(jié)”的字段,和/或字段可以被聲明為是最終的。如果字段不可變,則可以生成在不鎖定的情況下訪問字段的指令。在實(shí)施例中,另一種這樣的確定是執(zhí)行硬件是否具有事務(wù)支持。如果是,則為了訪問字段生成對(duì)硬件的指令的事務(wù)版本,以便于確保訪問被以事務(wù)方式處理。

在實(shí)施例中,另一種這樣的確定是字段是否是頻繁改變的和/或值是否是復(fù)雜的或頻繁訪問的。如果是,則生成指令來將字段存儲(chǔ)在諸如通過指針在值內(nèi)引用的容器之類的分開的容器內(nèi),而不是直接將字段存儲(chǔ)在存儲(chǔ)值的容器內(nèi)。指令經(jīng)由分開的容器訪問字段。在實(shí)施例中,另一種這樣的確定是值是否為已經(jīng)被劃分為子值的大值。值可以實(shí)際地被劃分并且存儲(chǔ)在分開的容器中,或者出于鎖定的目的值可以在邏輯上被劃分。如果值是已經(jīng)被劃分為子值的大值,則通過鎖定字段在其中駐留的子值來生成訪問字段的指令。在實(shí)施例中,另一種這樣的確定是值本身是否為另一個(gè)值的字段。如果是,則在此基礎(chǔ)上選擇鎖定策略。任何其他合適的確定可以被同時(shí)或者替代地做出。在實(shí)施例中,做出一系列的確定。從資源的視角被估計(jì)為最便宜的確定首先被執(zhí)行,而其他確定僅在需要的時(shí)候執(zhí)行。

在其他方面,公開了用于實(shí)現(xiàn)本文所描述的技術(shù)的計(jì)算設(shè)備的系統(tǒng)和計(jì)算機(jī)可讀介質(zhì)。

當(dāng)前第1頁(yè)1 2 3 
網(wǎng)友詢問留言 已有0條留言
  • 還沒有人留言評(píng)論。精彩留言會(huì)獲得點(diǎn)贊!
1