欧美在线观看视频网站,亚洲熟妇色自偷自拍另类,啪啪伊人网,中文字幕第13亚洲另类,中文成人久久久久影院免费观看 ,精品人妻人人做人人爽,亚洲a视频

動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法

文檔序號:6482574閱讀:167來源:國知局

專利名稱::動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法
技術(shù)領(lǐng)域
:本發(fā)明涉及一種動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法,具備重定向特性,能適用于多種目標(biāo)平臺,尤其適用于多源多目標(biāo)的二進(jìn)制翻譯平臺。
背景技術(shù)
:動態(tài)二進(jìn)制翻譯是虛擬執(zhí)行技術(shù)中應(yīng)用最為廣泛的方法,是為遺留代碼提供移植可能性和提高軟件的平臺適應(yīng)性的一種有效手段,它在不需要可執(zhí)行程序的源代碼的情況下,可以動態(tài)地將源機器平臺上的二進(jìn)制程序經(jīng)過轉(zhuǎn)換,運行于其他目標(biāo)機器平臺上。對于動態(tài)二進(jìn)制翻譯器自身而言,執(zhí)行性能是一個非常重要的衡量指標(biāo)。所謂執(zhí)行性能是指,以源程序在原架構(gòu)下運行的效率為參照,其在動態(tài)二進(jìn)制翻譯器提供的運行環(huán)境下的效率損失度越低,翻譯器的執(zhí)行性能越好。寄存器在計算機存儲體系結(jié)構(gòu)里處于最上層,是訪問速度最快的存儲介質(zhì),而且由于芯片大小的限制,通常寄存器數(shù)目不多,Intel的x86處理器只有8個通用寄存器,有些RISC體系結(jié)構(gòu)的寄存器數(shù)目稍多一些,但也只有幾十個左右的寄存器,當(dāng)然里面還包含很多特殊寄存器,能夠被翻譯器使用的就更少了。為了提高翻譯器翻譯后的代碼的執(zhí)行性能,動態(tài)二進(jìn)制翻譯領(lǐng)域需要采用一種技術(shù),它使得翻譯后的代碼塊能夠盡可能高效的利用寄存器這一稀缺資源。但是對于動態(tài)二進(jìn)制翻譯領(lǐng)域,考慮到動態(tài)執(zhí)行的實時性,分配方法開銷不能太高。因此技術(shù)人員必須在更高效的使用目標(biāo)平臺的寄存器和分配開銷之間尋求平衡。動態(tài)二進(jìn)制翻譯領(lǐng)域通常會有構(gòu)造超級塊的技術(shù),即把一些執(zhí)行熱度比較高的基本塊合起來,作為一個塊進(jìn)行編碼,形成一個超級塊。所謂超級塊,是指具有一個入口,一個或多個出口的代碼塊。對于超級塊內(nèi)的寄存器的分配,由于其執(zhí)行的熱度較高,對目標(biāo)代碼的質(zhì)量要求也更高,因此需要采用一種優(yōu)良的寄存器分配方法。目前,在動態(tài)二進(jìn)制翻譯領(lǐng)域可以使用如下方法完成寄存器分配任務(wù)-1、簡單的寄存器分配方法,這種分配算法通過對超級塊內(nèi)的變量號按目標(biāo)機寄存器數(shù)目進(jìn)行一次取模運算,得出的數(shù)字即是被分配的寄存器編號。如果該寄存器被同一條指令的其他變量占用,則嘗試下一個編號的寄存器。如果該寄存器沒有被同一條指令內(nèi)的其他變量占用,則把該寄存器內(nèi)容交換到內(nèi)存,然后分配該寄存器給當(dāng)前變量。如果該寄存器空閑,直接分配該寄存器給當(dāng)前變量。這種方法簡單有效,開銷小,適用于動態(tài)二進(jìn)制翻譯領(lǐng)域的及時性特性,但沒有利用超級塊內(nèi)變量的信息,使得分配結(jié)果不夠高效,寄存器使用效率不咼。2、全局寄存器分配方法,這種方法把超級塊常用的一些變量存放在全局寄存器中。全局變量是指在這個基本塊內(nèi)被使用次數(shù)(use-frcquency)最多的那個變量,把這些變量存放在某些寄存器中,在整個超級塊的生存期,對它們都不做替換。這種方法需要在分配前,先走査一下整個超級塊,收集超級塊內(nèi)所有變量的使用頻率信息。然后分配一些固定的寄存器給這些使用頻次最高的變量,其余變量使用簡單的寄存器分配方法進(jìn)行分配。這種方法利用了超級塊內(nèi)變量的信息,但使用不夠充分,只在開始階段利用收集到的信息固定分配了若干變量,對后續(xù)變量的分配過程則完全丟棄了這些信息。3、基于next-use信息的寄存器分配方法,這種方法根據(jù)超級塊內(nèi)變量的next-use信息進(jìn)行寄存器分配,所謂next-use信息是指該變量下次被使用的位置,這種方法簡單有效,適用于基本塊內(nèi)寄存器分配。對于由若干基本塊組成的超級塊,對變量信息的使用不夠充分,寄存器的分配結(jié)果不夠高效。4、圖染色分配方法,這種方法在靜態(tài)編譯器領(lǐng)域有著重要的地位,它是一種基于圖簡化思路的啟發(fā)式分配方法。它包括如下幾個步驟(1)變量活性信息的收集(2)干擾圖的構(gòu)造(3)圖精簡以及寄存器分配在靜態(tài)編譯器里,干擾信息的收集過程通常會經(jīng)過多次迭代,才能達(dá)到穩(wěn)定,即活性信息在每個節(jié)點都不再變化。在圖精簡過程中遇到圖不能再精簡的情況下通常會采用結(jié)合、冷凍、選擇溢出和實際溢出等各種高級手段來完善圖精簡的過程。該方法復(fù)雜度太高,分配開銷太大。從上述的四種寄存器分配方法可以看出,每種方法都有其固有的優(yōu)缺點,四者收集并利用信息的豐富程度呈遞增趨勢,同時,分配開銷和實現(xiàn)復(fù)雜度也隨之增加。對于前兩種寄存器分配方法,實現(xiàn)較簡單,但是利用超級塊內(nèi)變量的信息十分有限,不能達(dá)到有效的效果。第三種在分配結(jié)果與分配效率上對于一個基本塊達(dá)到了較好的折衷。最后一種方法充分利用了收集到的信息,對于靜態(tài)編譯器將是最好的方法,在動態(tài)二進(jìn)制翻譯領(lǐng)域,在一個超級塊內(nèi),按照此種分配方法所得到的寄存器使用效率的提高還不足以彌補為達(dá)到這種效果所付出的分配開銷。因此需要發(fā)明一種新型的適用于動態(tài)二進(jìn)制翻譯中超級塊的寄存器分配方法,既能有效的利用超級塊內(nèi)變量的信息,產(chǎn)生良好的分配結(jié)果,又不能有太多分配開銷。
發(fā)明內(nèi)容本發(fā)明的目的在于針對現(xiàn)有技術(shù)的不足,提供一種動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法,滿足動態(tài)二進(jìn)制翻譯器領(lǐng)域中超級塊的寄存器分配的特殊需求,比如二進(jìn)制翻譯系統(tǒng)對分配開銷的敏感性,在分配開銷和分配結(jié)果中達(dá)到折衷。為實現(xiàn)上述目的,本發(fā)明設(shè)計的一種寄存器分配方法,是一種根據(jù)二進(jìn)制翻譯系統(tǒng)超級塊的特性簡化了的圖染色寄存器分配方法。因為分配對象是超級塊,在分配開銷上要介于基于next-use的寄存器分配方法和傳統(tǒng)的圖染色寄存器分配方法。它利用超級塊內(nèi)變量的活性信息構(gòu)造干擾圖,然后把寄存器分配問題轉(zhuǎn)化為干擾圖的精簡問題,使得超級塊的目標(biāo)代碼能夠最大限度的使用目標(biāo)平臺寄存器,具有目標(biāo)代碼執(zhí)行效率高的特性。本發(fā)明方法的作用位置動態(tài)二進(jìn)制翻譯器為了優(yōu)化性能,通常會使用profile技術(shù)獲取執(zhí)行熱路徑,并且構(gòu)造超級塊,在超級塊構(gòu)造的過程中需要調(diào)用本方法完成目標(biāo)平臺寄存器的分配工作。本發(fā)明進(jìn)行寄存器分配的具體步驟如下1)初始化寄存器分配器的目標(biāo)平臺,包括目標(biāo)平臺的寄存器數(shù)目,目標(biāo)平臺的寄存器之間的數(shù)據(jù)移動機器指令,內(nèi)存到寄存器的數(shù)據(jù)移動機器指令以及寄存器到內(nèi)存的數(shù)據(jù)移動機器指令;2)初始化寄存器分配器內(nèi)部數(shù)據(jù)結(jié)構(gòu),包括初始化目標(biāo)平臺寄存器狀態(tài)的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù),所有目標(biāo)平臺寄存器狀態(tài)設(shè)為空閑,所匹配的變量設(shè)為空,所在指令設(shè)為空;初始化所有超級塊變量所在位置為內(nèi)存;清空用來存放超級塊指令干擾列表的隊列;初始化用來存放單條指令里變量干擾信息的干擾列表為空;初始化寄存器預(yù)分配結(jié)果表為空;3)從每個超級塊尾部到頭部遍歷,依次査看每條指令的變量,從中先找到DEF類型的變量,査看干擾列表里是否有這個變量,如果有,則從干擾列表里移除該變量,再找到USE類型的變量,查看干擾列表里是否有這個變量,如果沒有,則插入這個變量;遍歷完這條指令的所有變量后,把干擾列表插入到隊列頭部,并把該干擾列表作為產(chǎn)生下一條指令的干擾列表的基礎(chǔ),直到超級塊的第一條指令為止,得到超級塊指令干擾列表組成的隊列,完成干擾信息的收集;4)初始化干擾圖為不存在干擾邊;從隊首到隊尾遍歷超級塊指令干擾列表組成的隊列,依次處理隊列里的干擾列表,凡在同一個列表的兩個變量,都在干擾圖里對應(yīng)這對變量的位置記錄一條干擾邊;直到隊列尾部的干擾列表被處理,干擾圖的生成過程結(jié)束;5)通過干擾圖査看每個變量的干擾邊,如果干擾邊數(shù)目少于目標(biāo)平臺寄存器數(shù)目,則把該變量入棧,并刪除干擾圖里與該變量相關(guān)的干擾邊,如果不少于目標(biāo)平臺寄存器數(shù)目,則查看下一個變量,如果干擾圖里剩余變量的干擾邊都不少于目標(biāo)平臺寄存器數(shù)目,則選擇其中一個變量作為犧牲變量,從干擾圖里刪除,并刪除與之相關(guān)的干擾邊;然后再査看下一個變量,直到干擾圖所有變量入棧為止,干擾圖簡化過程結(jié)束;6)從棧頂依次彈出變量,找到一個沒有分配給與其存在干擾關(guān)系變量的寄存器,分配給該變量,把結(jié)果記錄在預(yù)分配結(jié)果表里。直到棧空為止,寄存器預(yù)分配結(jié)束;7)根據(jù)不同翻譯需要對超級塊中的變量進(jìn)行寄存器的分配,分為普通分配、強制要求特定寄存器分配、強制要求非特定寄存器分配;8)對于普通分配,依次査看寄存器的狀態(tài),如果有寄存器狀態(tài)是已被分配,并且被分配的對象是該變量,則繼續(xù)保持這種分配,否則査看預(yù)分配結(jié)果表;如果有寄存器分配給該變量,并且該寄存器狀態(tài)是已被分配,則查看干擾圖,如果被分配給的變量與當(dāng)前變量不存在干擾關(guān)系,則直接分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)內(nèi)存的值裝載進(jìn)該寄存器,如果存在干擾關(guān)系,保存該寄存器里的值到被分配給的變量對應(yīng)的內(nèi)存,然后分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量的值裝載進(jìn)該寄存器;如果該寄存器為受保護狀態(tài),則査看所有的寄存器,如果存在空閑狀態(tài)的寄存器,則分配它,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器,如果沒有空閑寄存器,則查找一個己被分配的寄存器,保存該已被分配的寄存器里的值到該已被分配的寄存器對應(yīng)的變量的內(nèi)存,然后分配該己被分配的寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器;如果預(yù)分配結(jié)果里沒有寄存器分配給它,則找到一個非受保護狀態(tài)的寄存器,優(yōu)先選擇空閑寄存器分配給該變量,如果找到的是空閑寄存器,且該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器,如果找到的是已被分配的寄存器,首先把該已給分配的寄存器的值保存在該已被分配的寄存器對應(yīng)的變量的內(nèi)存,如果該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器;9)對于強制要求特定寄存器分配,如果強制要求寄存器己被分配的變量恰好是該變量,則繼續(xù)保持這種分配;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量存在干擾關(guān)系,則把強制要求特定寄存器的值保存到對應(yīng)變量的內(nèi)存,完成數(shù)據(jù)保護處理,把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量9不存在干擾關(guān)系,則把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器;10)對于強制要求非特定寄存器分配,先保存強制要求非特定寄存器的狀態(tài)到一個臨時變量,如果強制要求非特定寄存器已經(jīng)分配給了該變量,則保存強制要求非特定寄存器到該變量對應(yīng)的內(nèi)存,更改臨時變量的狀態(tài)為空閑,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果;如果強制要求非特定寄存器沒有分配給該變量,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果。本發(fā)明的寄存器分配方法具有實質(zhì)性進(jìn)步和顯著的優(yōu)點①本發(fā)明可以根據(jù)不同的目標(biāo)平臺進(jìn)行相應(yīng)的寄存器分配,具有可重定向性,只需很小的改動,就能適用于多種目標(biāo)平臺。與現(xiàn)有寄存器分配方法比,對二進(jìn)制翻譯系統(tǒng)的支持有著特殊的處理,尤其是有著多源多目標(biāo)的特性,只需變更兩個回調(diào)函數(shù)和目標(biāo)平臺的寄存器數(shù)目,就能夠應(yīng)用,非常的便利。②本發(fā)明對二進(jìn)制翻譯系統(tǒng)中寄存器分配需要的各種應(yīng)用場景有著良好的支持。提供豐富的接口滿足動態(tài)二進(jìn)制翻譯對寄存器的各種分配要求。③分配開銷小,分配結(jié)果好。基于簡化的圖染色寄存器分配策略,具有遍歷一遍超級塊就能完成干擾信息收集過程,一遍完成干擾圖簡化過程等特性,取消了結(jié)合,冷凍等高級過程。適用于動態(tài)二進(jìn)制翻譯系統(tǒng)領(lǐng)域超級塊粒度內(nèi)寄存器的分配。在基于next-use信息寄存器分配方法和經(jīng)典的圖染色寄存器分配方法之間,結(jié)合超級塊的特點,找到了開銷與結(jié)果的較佳平衡點。具體實施例方式為更好地理解本發(fā)明的技術(shù)方案,以下結(jié)合附圖并通過具體的實施例作進(jìn)一步描述。以下實施例不構(gòu)成對本發(fā)明的限定。CrossBit是一個動態(tài)二進(jìn)制翻譯系統(tǒng),它可以為執(zhí)行在多種不同體系結(jié)構(gòu)的源程序,通過翻譯和優(yōu)化的方法,提供異構(gòu)架構(gòu)下的執(zhí)行環(huán)境。為了實現(xiàn)多源多目標(biāo),CrossBit使用了中間代碼層,這樣會減少翻譯路徑。只需要把前端二進(jìn)制映像程序(前端)翻譯成中間代碼塊,然后再把中間代碼塊翻譯成對應(yīng)的目標(biāo)平臺代碼(后端),就能形成一種二進(jìn)制翻譯器。如果目標(biāo)平臺改變,只需改變一個后端。目前,CrossBit支持SimpleScalar,MIPS,X86,SPARC前端,X86和SPARC后端。CrossBit采用VINST作為中間指令集,它是CrossBit項目組自己設(shè)計的一套中間指令集,是一種低層次的虛擬精簡機器指令系統(tǒng),具有無窮多個32位虛擬寄存器、Load-Store風(fēng)格體系結(jié)構(gòu)、單一的偏址尋址模式。寄存器分配方法面對的對象是這些中間指令組成的中間代碼塊。CrossBit的執(zhí)行框架是,首先加載源二進(jìn)制映像,找出源映像的入口地址,之后在TCache里査找對應(yīng)該入口的目標(biāo)代碼塊,所謂TCache是一塊內(nèi)存區(qū)域,用來存放翻譯好的目標(biāo)代碼塊,如果查找成功,則切換上下文,執(zhí)行這個目標(biāo)代碼塊,如果査找失敗,則啟動CrossBit的前端解碼器,對源映像中對應(yīng)該入口地址的基本塊解碼成中間指令,并封裝成中間代碼塊(VBlock),然后調(diào)用CrossBit的后端編碼器把中間指令塊轉(zhuǎn)換成目標(biāo)代碼塊(TBlock)。然后提交到TCache里,然后再次査找TCache,就會出現(xiàn)TCache命中,這時再進(jìn)行上下文的切換,進(jìn)行目標(biāo)代碼塊的執(zhí)行。當(dāng)目標(biāo)代碼塊執(zhí)行完畢后,將會返回到CrossBit的上下文,進(jìn)行下一個輪回的操作。如此往復(fù),直到整個程序執(zhí)行完畢。在執(zhí)行的過程中,CrossBit會在每個TBlock里設(shè)置一個計數(shù)器,每執(zhí)行一次將會加一,當(dāng)該基本塊執(zhí)行的次數(shù)超過設(shè)定的閥值時,將會把該TBlock設(shè)定為需要做超級塊的對象,到執(zhí)行環(huán)境切換到CrossBit的時候,將會對該TBlock對應(yīng)的VBlock進(jìn)行超級塊構(gòu)造。然后再對構(gòu)造好的超級VBlock做編碼,在編碼的過程中,將調(diào)用本發(fā)明提出的寄存器分配方法。本發(fā)明主要包括如下幾個過程,特定目標(biāo)平臺的寄存器分配器的初始化、寄存器分配前的初始化、干擾信息的收集、干擾圖的構(gòu)造、干擾圖的精簡、預(yù)分配以及具體的寄存器分配過程。不失一般性,本發(fā)明實施例依托于CrossBit的執(zhí)行框架以及超級塊的生成技術(shù)。1)初始化寄存器分配器的目標(biāo)平臺初始化寄存器分配器的目標(biāo)平臺,包括目標(biāo)平臺的寄存器數(shù)目,目標(biāo)平臺的寄存器之間的數(shù)據(jù)移動機器指令,內(nèi)存到寄存器的數(shù)據(jù)移動機器指令以及寄存器到內(nèi)存的數(shù)據(jù)移動機器指令。本實施例使用構(gòu)造函數(shù)RegAllocator(XTUInt8num_regs,CBOfSpilllncb—spill—in,CBOfSpillOutcb_spill_out,CBOfRegToRegcb—regtoreg)創(chuàng)建目標(biāo)平臺的寄存器分配器,寄存器的數(shù)目通過參數(shù)num一regs傳遞,cb—spill一in、cb一印il1—out、cb一regtoreg都是函數(shù)指針,分別指向目標(biāo)平臺上能夠完成內(nèi)存到寄存器,寄存器到內(nèi)存,寄存器到寄存器等功能的函數(shù)。2)寄存器分配前的初始化初始化寄存器分配器內(nèi)部數(shù)據(jù)結(jié)構(gòu),包括初始化目標(biāo)平臺寄存器狀態(tài)的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù),所有目標(biāo)平臺寄存器狀態(tài)設(shè)為空閑,所匹配的變量設(shè)為空,所在指令設(shè)為空;初始化所有超級塊變量所在位置為內(nèi)存;清空用來存放超級塊指令干擾列表的隊列;初始化用來存放單條指令里變量干擾信息的干擾列表為空;初始化寄存器預(yù)分配結(jié)果表為空。本實施例中,使用ra—reg—table[reg—num]保存目標(biāo)平臺寄存器的狀態(tài),reg—num是目標(biāo)平臺的寄存器數(shù)目,結(jié)構(gòu)體RegUsage包含status(free,allocated,reserved)、mapped_to禾口inst信息,分別表示寄存器的狀態(tài),被匹配的虛擬寄存器編號,所處指令的編號;使用boolra_vreg_spilied[MAX一VREG一NUM]保存中間指令中虛擬寄存器的存在位置,其中MAX—VREG—NUM表示VBlock里的最多包含的虛擬寄存器的數(shù)目,通常根據(jù)經(jīng)驗值設(shè)定;使用RegListsreg—lists是存放干擾列表的隊列,用來保存收集到的干擾信息,其中typedefstd::queue〈RegList〉RegLists,typedefstd::set〈XTRegNum〉RegList;使用XTInt32reg4vars[MAX—VREG—NUM]保存寄存器預(yù)分配結(jié)果。i、ra—reg_table[reg_num]的初始化初始化該數(shù)組里面所有元素的status域為free,inst域設(shè)為0,mapped—to域設(shè)為-1。表示寄存器狀態(tài)為空閑,所匹配的變量為空,所在指令為空,所有寄存器都可以被分配。ii、ra—vreg—spilled[MAX_VREG_NUM]的初始化初始化該數(shù)組里的所有元素為false。表明所有虛擬寄存器都在內(nèi)存里。如果該值是true,則表明該虛擬寄存器在寄存器里。iii、RegListsreg_lists的初始化清空里面的數(shù)據(jù)。iv、reg4vars[MAX—VREG_NUM]的初始化初始化每個虛擬寄存器的預(yù)分配結(jié)果為-1,表示為空。3)干擾信息收集從每個超級塊尾部到頭部遍歷,依次查看每條指令的變量,從中先找到DEF類型的變量,査看干擾列表里是否有這個變量,如果有,則從干擾列表里移除該變量,再找到USE類型的變量,查看干擾列表里是否有這個變量,如果沒有,則插入這個變量;遍歷完這條指令的所有變量后,把干擾列表插入到隊列頭部,并把該干擾列表作為產(chǎn)生下一條指令的干擾列表的基礎(chǔ),直到超級塊的第一條指令為止,得到超級塊指令干擾列表組成的隊列,完成干擾信息的收集。本實施例使用了collectGraphlnfo(VBlock*vb)函數(shù)完成這個任務(wù),其中vb是VBlock的指針,指向VBlock的地址,這里的VBlock是超級VBlock。VBlock里存放的是一條條的VInst指令,干擾信息的收集過程為從尾到頭掃描所有VInst指令,取出每條指令的虛擬寄存器類型(VReg)的參數(shù),根據(jù)其虛擬寄存器的編號以及其類型(Operand::VREG_DEF或者Operand::VREGJJSE),放進(jìn)列表。比如一條指令seq(seq是該指令在VBlock中的位置)的某個參數(shù)類型是VREG—DEF,則査看當(dāng)前列表是否包含該編號,如果存在,則從列表里移除這個編號,否則繼續(xù)査看下一個參數(shù)。如果某個參數(shù)類型為VREG一USE,則查看當(dāng)前列表是否包含該編號,如果包含則繼續(xù)下一個參數(shù),否則,則把該參數(shù)放進(jìn)列表。這一過程直到該指令所有參數(shù)都做過處理為止。把得到的列表放進(jìn)reg一lists頭部,并以該列表為基礎(chǔ),進(jìn)行下一條指令的掃描。這一過程直到該超級虛擬塊頭部為止。4)干擾圖的生成初始化干擾圖為不存在干擾邊;從隊首到隊尾遍歷超級塊指令干擾列表組成的隊列,依次處理隊列里的干擾列表,凡在同一個列表的兩個變量,都在干擾圖里對應(yīng)這對變量的位置記錄一條干擾邊;直到隊列尾部的干擾列表被處理,干擾圖的生成過程結(jié)束。本實施例用二維數(shù)組來表示干擾圖,初始化干擾圖彼此不存在干擾邊即為把該二維數(shù)組所有元素初始化為0,完成干擾圖的初始化工作。然后從頭到尾進(jìn)行遍歷regjists,依次取出每個列表,依次對每個列表做處理,凡在同一個列表的虛擬寄存器,則其相互之間存在干擾關(guān)系,則在干擾圖里記錄一條干擾邊,在本實施例中記錄干擾邊則體現(xiàn)為,一維下標(biāo)和二維下標(biāo)分別表示兩個虛擬寄存器的編號,在數(shù)組的這兩個下標(biāo)所對應(yīng)的元素值置為1。直到reg—lists尾部為止,完成干擾圖的生成。5)干擾圖的精簡通過干擾圖査看每個變量的干擾邊,如果干擾邊數(shù)目少于目標(biāo)平臺寄存器數(shù)目,則把該變量入棧,并刪除干擾圖里與該變量相關(guān)的干擾邊,如果不少于目標(biāo)平臺寄存器數(shù)目,則查看下一個變量,如果干擾圖里剩余變量的干擾邊都不少于目標(biāo)平臺寄存器數(shù)目,則選擇其中一個變量作為犧牲變量,從干擾圖里刪除,并刪除與之相關(guān)的干擾邊;然后再査看下一個變量,直到千擾圖所有變量入棧為止,干擾圖簡化過程結(jié)束。本實施例表現(xiàn)為根據(jù)表示干擾圖的那個二維數(shù)組,依次檢査對應(yīng)每個虛擬寄存器對應(yīng)編號的行數(shù)組元素,統(tǒng)計內(nèi)容為l的數(shù)目,如果沒有超過寄存器數(shù)目,則把該虛擬寄存器編號入棧,并把對應(yīng)該編號的列數(shù)組元素清零。遇到干擾圖不能繼續(xù)簡化時,挑選其中一個虛擬寄存器,把與該虛擬寄存器對應(yīng)編號的列數(shù)組元素清零,繼續(xù)干擾圖的簡化工作。直到干擾圖精簡完畢為止,得到能夠染色的虛擬寄存器棧。6)寄存器預(yù)分配從虛擬寄存器棧棧頂依次彈出變量,找到一個沒有分配給與其存在干擾關(guān)系變量的寄存器,分配給該變量,把結(jié)果記錄在預(yù)分配結(jié)果表里。直到棧空為止,寄存器預(yù)分配結(jié)束。在本實施例中,具體為對虛擬寄存器棧進(jìn)行彈棧操作,査看該虛擬寄存器的干擾節(jié)點的分配結(jié)果,通過訪問備份的干擾圖找到所有干擾節(jié)點,通過使用一個臨時數(shù)組表示被當(dāng)前虛擬寄存器的所有干擾節(jié)點用掉的寄存器,從該臨時數(shù)組里找出一個空閑的寄存器給棧頂虛擬寄存器,在reg4vars做記錄,即把以該虛擬寄存器編號為下標(biāo)的元素內(nèi)容置為該寄存器。繼續(xù)彈棧操作,直到棧清空,完成寄存器的預(yù)分配工作。7)寄存器的分配根據(jù)不同翻譯需要對超級塊中的變量進(jìn)行寄存器的分配,分為普通分配、強制要求特定寄存器分配、強制要求非特定寄存器分配。當(dāng)變量沒有特殊寄存器要求,即目標(biāo)平臺上任何一個寄存器都可以,這種情況將使用普通分配。當(dāng)變量有寄存器的要求,比如當(dāng)目標(biāo)平臺為x86的情況,某個變量必須要用ESP寄存器,這種情況下將使用強制要求特定寄存器分配。當(dāng)變量需要除了某個特定寄存器之外的其他寄存器,這種情況下將使用強制要求非特定寄存器分配。8)普通分配對于普通分配,依次查看寄存器的狀態(tài),如果有寄存器狀態(tài)是已被分配,并且被分配的對象是該變量,則繼續(xù)保持這種分配;否則査看預(yù)分配結(jié)果表,如果有寄存器分配給該變量,并且該寄存器狀態(tài)是已被分配,則査看干擾圖,如果被分配給的變量與當(dāng)前變量不存在干擾關(guān)系,則直接分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)內(nèi)存的值裝載進(jìn)該寄存器,如果存在干擾關(guān)系,保存該寄存器里的值到被分配給的變量對應(yīng)的內(nèi)存,然后分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量的值裝載進(jìn)該寄存器;如果該寄存器為受保護狀態(tài),則查看所有的寄存器,如果存在空閑狀態(tài)的寄存器,則分配它,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器,如果沒有空閑寄存器,則査找一個已被分配的寄存器,保存該已被分配的寄存器里的值到該已被分配的寄存器對應(yīng)的變量的內(nèi)存,然后分配該已被分配的寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器;如果預(yù)分配結(jié)果里沒有寄存器分配給它,則找到一個非受保護狀態(tài)的寄存器,優(yōu)先選擇空閑寄存器分配給該變量,如果找到的是空閑寄存器,且該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器,如果找到的是己被分配的寄存器,首先把該已給分配的寄存器的值保存在該已被分配的寄存器對應(yīng)的變量的內(nèi)存,如果該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器。本實施例使用regAlloc(XTRegNumvreg,RegAccessModemode)完成普通分配。參數(shù)vreg是需要寄存器的虛擬寄存器,mode表示該虛擬寄存器的訪問類型(DEF或者USE)。主要有如下歩驟①順序查看每個寄存器的狀態(tài),如果是allocated并且和它匹配的是vreg,則查看vreg是否在寄存器里(通過査看spilled標(biāo)志),如果不在寄存器里,需要做spillin,并修改spilled標(biāo)志。更新寄存器的inst值。返回該寄存器給vreg用。分配過程結(jié)束。返回。如果遍歷所有的寄存器狀態(tài),沒有符合這種條件的,進(jìn)入步驟②;②査看reg4vars[vreg],如果不小于0,則查看編號為reg4vars[vreg]的每個寄存器的狀態(tài),如果是free,以此寄存器作為分配結(jié)果,進(jìn)入步驟④,如果是reserved或者所在所在指令為當(dāng)前指令,則需要重新分配進(jìn)入步驟③,如果是allocated,查看干擾圖,如果該寄存器被分配的虛擬寄存器與vreg相互干擾,則把該寄存器內(nèi)容spillout到內(nèi)存,否則不需要spillout到內(nèi)存,然后以此寄存器作為分配結(jié)果。分配過程結(jié)束,進(jìn)入步驟④;③査看每個寄存器狀態(tài),如果是free,則以此寄存器作為分配結(jié)果,如果已分配給同條指令的其他虛擬寄存器或者狀態(tài)為reserved,則繼續(xù)查看下一個寄存器,只到找到一個合適的寄存器為止,如果是分配給了非當(dāng)前指令的其他虛擬寄存器,査看干擾圖,如果該寄存器被分配的虛擬寄存器與vreg相互干擾,則把該寄存器內(nèi)容spillout到內(nèi)存,否則不需要spillout到內(nèi)存,并以此寄存器作為分配結(jié)果。進(jìn)入步驟④;@如果mode為USE,把vreg內(nèi)容spillin到分配到的寄存器,并更新vreg的存在位置為在寄存器內(nèi)。更新分配到的那個寄存器的狀態(tài),即把status域更新為allocated,mapped_to土或更新為vreg,inst±或更新為當(dāng)前指令。返回分配結(jié)果。9)強制要求特定寄存器分配對于強制要求特定寄存器分配,如果強制要求寄存器已被分配的變量恰好是該變量,則繼續(xù)保持這種分配;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量存在干擾關(guān)系,則把強制要求特定寄存器的值保存到對應(yīng)變量的內(nèi)存,完成數(shù)據(jù)保護處理,把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量不存在干擾關(guān)系,則把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器。本實施例使用regAllocForce(XTRegNumvreg,XTRegNumexpect,RegAccessMode)來完成強制要求某個特定寄存器給虛擬寄存器。主要有如下步驟①查看寄存器expect的狀態(tài),如果是reserved,發(fā)生死鎖,返回錯誤碼,結(jié)束。否則進(jìn)入②;②如果expect的狀態(tài)是allocated,則査看其map對象是否vreg,如果是,則用當(dāng)前指令位置vinst—seq更新ra_reg_table[expect].inst,然后查看spilled標(biāo)志,如果被溢出了,并且是USE類型,還需要把vreg的內(nèi)容spillin到expect寄存器里,并且修改spilled標(biāo)志,然后返回expect,結(jié)束。如果其map對象不是vreg進(jìn)入步驟③;③査看ra—reg—table[expect],inst,如果是當(dāng)前指令,返回錯誤碼,結(jié)束,否則,查看干擾圖,如果expect寄存器匹配對象與vreg有干擾關(guān)系,則spillout該expect寄存器,如果沒有干擾關(guān)系,不需要spillout操作,然后査找vreg以前的分配結(jié)果,如果已被分配過寄存器,修改原來寄存器的狀態(tài),比如status改為free,mapped_to改為-1,并更新expect寄存器的狀態(tài),比如mapped—to值為vreg,inst更新為當(dāng)前指令,status改為allocated。并把該寄存器的值裝載到expect寄存器里,返回分配結(jié)果,結(jié)束。如果沒被分配過寄存器,如果是DEF,什么都不做,如果mode是USE,則spillin虛擬寄存器vreg到expect。更新expect寄存器的狀態(tài),比如mapped—to值為vreg,inst更新為當(dāng)前指令,status改為allocated。返回分配結(jié)果e鄧ect,結(jié)束。10)強制要求非特定寄存器分配對于強制要求非特定寄存器分配,先保存強制要求非特定寄存器的狀態(tài)到一個臨時變量,如果強制要求非特定寄存器已經(jīng)分配給了該變量,則保存強制要求非特定寄存器到該變量對應(yīng)的內(nèi)存,更改臨時變量的狀態(tài)為空閑,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果;如果強制要求非特定寄存器沒有分配給該變量,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果。本實施例使用regAllocForceExcept(XTRegNumvreg,XTRegNumexcept,RegAccessModemode)完成分配除了exc印t以外的其他任一^1^寄存器給vreg的功能。主要有如下步驟①保存寄存器exc印t的狀態(tài)到temp。查看寄存器exc印t對應(yīng)的虛擬寄存器是否vreg,如果是,則spillout寄存器exc印t內(nèi)容到內(nèi)存,修改temp狀態(tài)為free,然后進(jìn)入步驟②;②修改except狀態(tài)為reserved,本例中具體操作為ra一reg—table[except]=reserved。修改為reserved狀態(tài)的目的是杜絕調(diào)用regAlloc函數(shù)對vreg進(jìn)行分配時,得到exc印t的結(jié)果。然后調(diào)用函數(shù)regAlloc(vreg,mode)進(jìn)行分配。最后使用te卿值恢復(fù)exc印t的狀態(tài)。返回分配結(jié)果。結(jié)束。本實施例還使用了regAllocReserve(XTRegNumtreg)完成寄存器的保護工作。主要應(yīng)用于避免某個寄存器被使用。主要步驟如下①如果treg狀態(tài)是allocated,查看其inst值,如果等于當(dāng)前指令,則出錯,否則使用regSpillOut(treg)操作完成寄存器值保存的工作,并修改mappecLto為-l。進(jìn)入步驟②。如果是非allocated狀態(tài),則什么都不做。進(jìn)入步驟②。②修改treg的狀態(tài)為reserved,返回。結(jié)束。本實施例使用regAllocRelease(XTRegNumtreg)完成寄存器釋放的工作,這部分工作主要回收不再被使用的寄存器,以備其他寄存器使用。也主動應(yīng)對regAllocReserve函數(shù)對寄存器的reserved操作。具體操作為修改treg的狀態(tài)為free。本實施例使用regSpillOut(XTRegNumphysical—reg)完成寄存器到內(nèi)存的數(shù)據(jù)轉(zhuǎn)移工作。具體實現(xiàn)為找到physical—reg對應(yīng)的vreg,然后調(diào)用對應(yīng)平臺的回調(diào)函數(shù)(打a一cb—spi11—out)(physical—reg,(XTMemAddr)ra—spill—pool+vreg)完成physical—reg的內(nèi)容到vreg對應(yīng)的內(nèi)存池位置的移動。結(jié)束。函數(shù)ra—cb_spill—out是條根據(jù)目標(biāo)平臺設(shè)定的寄存器到內(nèi)存的數(shù)據(jù)移動機器碼指令。對于寄存器溢入,采用regSpillIn的操作,即regSpillOut的鏡像操作。regSpillln的操作是regSpillOut的鏡像操作。權(quán)利要求1、一種動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法,其特征在于包括如下步驟1)初始化寄存器分配器的目標(biāo)平臺,包括目標(biāo)平臺的寄存器數(shù)目,目標(biāo)平臺的寄存器之間的數(shù)據(jù)移動機器指令,內(nèi)存到寄存器的數(shù)據(jù)移動機器指令以及寄存器到內(nèi)存的數(shù)據(jù)移動機器指令;2)初始化寄存器分配器內(nèi)部數(shù)據(jù)結(jié)構(gòu),包括初始化目標(biāo)平臺寄存器狀態(tài)的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù),所有目標(biāo)平臺寄存器狀態(tài)設(shè)為空閑,所匹配的變量設(shè)為空,所在指令設(shè)為空;初始化所有超級塊變量所在位置為內(nèi)存;清空用來存放超級塊指令干擾列表的隊列;初始化用來存放單條指令里變量干擾信息的干擾列表為空;初始化寄存器預(yù)分配結(jié)果表為空;3)從每個超級塊尾部到頭部遍歷,依次查看每條指令的變量,從中先找到DEF類型的變量,查看干擾列表里是否有這個變量,如果有,則從干擾列表里移除該變量,再找到USE類型的變量,查看干擾列表里是否有這個變量,如果沒有,則插入這個變量;遍歷完這條指令的所有變量后,把干擾列表插入到隊列頭部,并把該干擾列表作為產(chǎn)生下一條指令的干擾列表的基礎(chǔ),直到超級塊的第一條指令為止,得到超級塊指令干擾列表組成的隊列,完成干擾信息的收集;4)初始化干擾圖為不存在干擾邊;從隊首到隊尾遍歷超級塊指令干擾列表組成的隊列,依次處理隊列里的干擾列表,凡在同一個列表的兩個變量,都在干擾圖里對應(yīng)這對變量的位置記錄一條干擾邊;直到隊列尾部的干擾列表被處理,干擾圖的生成過程結(jié)束;5)通過干擾圖查看每個變量的干擾邊,如果干擾邊數(shù)目少于目標(biāo)平臺寄存器數(shù)目,則把該變量入棧,并刪除干擾圖里與該變量相關(guān)的干擾邊,如果不少于目標(biāo)平臺寄存器數(shù)目,則查看下一個變量,如果干擾圖里剩余變量的干擾邊都不少于目標(biāo)平臺寄存器數(shù)目,則選擇其中一個變量作為犧牲變量,從干擾圖里刪除,并刪除與之相關(guān)的干擾邊;然后再查看下一個變量,直到干擾圖所有變量入棧為止,干擾圖簡化過程結(jié)束;6)從棧頂依次彈出變量,找到一個沒有分配給與其存在干擾關(guān)系變量的寄存器,分配給該變量,把結(jié)果記錄在預(yù)分配結(jié)果表里;直到??諡橹梗拇嫫黝A(yù)分配結(jié)束;7)根據(jù)不同翻譯需要對超級塊中的變量進(jìn)行寄存器的分配,分為普通分配、強制要求特定寄存器分配、強制要求非特定寄存器分配;8)對于普通分配,依次查看寄存器的狀態(tài),如果有寄存器狀態(tài)是已被分配,并且被分配的對象是該變量,則繼續(xù)保持這種分配,否則查看預(yù)分配結(jié)果表;如果有寄存器分配給該變量,并且該寄存器狀態(tài)是已被分配,則查看干擾圖,如果被分配給的變量與當(dāng)前變量不存在干擾關(guān)系,則直接分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)內(nèi)存的值裝載進(jìn)該寄存器,如果存在干擾關(guān)系,保存該寄存器里的值到被分配給的變量對應(yīng)的內(nèi)存,然后分配該寄存器,如果該變量后續(xù)指令是被使用的,把變量的值裝載進(jìn)該寄存器;如果該寄存器為受保護狀態(tài),則查看所有的寄存器,如果存在空閑狀態(tài)的寄存器,則分配它,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器,如果沒有空閑寄存器,則查找一個已被分配的寄存器,保存該已被分配的寄存器里的值到該已被分配的寄存器對應(yīng)的變量的內(nèi)存,然后分配該已被分配的寄存器,如果該變量后續(xù)指令是被使用的,把變量對應(yīng)的內(nèi)存里的值裝載進(jìn)該寄存器;如果預(yù)分配結(jié)果里沒有寄存器分配給它,則找到一個非受保護狀態(tài)的寄存器,優(yōu)先選擇空閑寄存器分配給該變量,如果找到的是空閑寄存器,且該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器,如果找到的是已被分配的寄存器,首先把該已給分配的寄存器的值保存在該已被分配的寄存器對應(yīng)的變量的內(nèi)存,如果該變量后續(xù)指令是被使用的,把該變量對應(yīng)內(nèi)存里的值裝載進(jìn)該寄存器;9)對于強制要求特定寄存器分配,如果強制要求寄存器已被分配的變量恰好是該變量,則繼續(xù)保持這種分配;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量存在干擾關(guān)系,則把強制要求特定寄存器的值保存到對應(yīng)變量的內(nèi)存,完成數(shù)據(jù)保護處理,把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器;如果強制要求寄存器被分配的變量不是該變量,且被分配的變量與該變量不存在干擾關(guān)系,則把該強制要求特定寄存器分配給該變量,如果該變量后續(xù)指令是被使用的并且該變量在內(nèi)存里,把該變量對應(yīng)的內(nèi)存的數(shù)據(jù)裝載到強制要求特定寄存器,如果該變量后續(xù)指令是被使用的并且該變量在寄存器里,把該變量對應(yīng)的寄存器的數(shù)據(jù)裝載到強制要求特定寄存器;10)對于強制要求非特定寄存器分配,先保存強制要求非特定寄存器的狀態(tài)到一個臨時變量,如果強制要求非特定寄存器已經(jīng)分配給了該變量,則保存強制要求非特定寄存器到該變量對應(yīng)的內(nèi)存,更改臨時變量的狀態(tài)為空閑,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果;如果強制要求非特定寄存器沒有分配給該變量,更改強制要求非特定寄存器的狀態(tài)為受保護的,然后對該變量進(jìn)行普通分配,將受保護的強制要求非特定寄存器改回臨時變量的值,并以普通分配的結(jié)果作為分配結(jié)果。全文摘要本發(fā)明涉及一種動態(tài)二進(jìn)制翻譯系統(tǒng)中超級塊的寄存器分配方法,是一種根據(jù)二進(jìn)制翻譯系統(tǒng)超級塊的特性簡化了的圖染色寄存器分配方法。利用超級塊內(nèi)變量的活性信息構(gòu)造干擾圖,然后把寄存器分配問題轉(zhuǎn)化為干擾圖的精簡問題,使得超級塊的目標(biāo)代碼能夠最大限度的使用目標(biāo)平臺寄存器,具有目標(biāo)代碼執(zhí)行效率高的特性。分配時根據(jù)動態(tài)二進(jìn)制翻譯領(lǐng)域的不同需要對基本塊中的變量進(jìn)行寄存器的分配,分為普通分配、強制要求特定寄存器分配、強制要求非特定寄存器分配。本發(fā)明具有可重定向特性,對于超級塊具有分配效果好、分配開銷低的特點,適用于多種目標(biāo)平臺,尤其適用于多源多目標(biāo)的二進(jìn)制翻譯平臺。文檔編號G06F9/45GK101546271SQ200910050440公開日2009年9月30日申請日期2009年4月30日優(yōu)先權(quán)日2009年4月30日發(fā)明者姜玲燕,李曉龍,梁阿磊,管海兵,蔡戰(zhàn)舉申請人:上海交通大學(xué)
網(wǎng)友詢問留言 已有0條留言
  • 還沒有人留言評論。精彩留言會獲得點贊!
1
萨迦县| 醴陵市| 蓝山县| 普格县| 临邑县| 武义县| 秭归县| 旅游| 进贤县| 大竹县| 高陵县| 余干县| 江孜县| 鹤山市| 万源市| 南投市| 游戏| 金乡县| 鲁甸县| 吕梁市| 白朗县| 资溪县| 梅河口市| 崇信县| 临邑县| 商丘市| 西乡县| 怀集县| 洛南县| 麟游县| 增城市| 大渡口区| 花莲县| 阜康市| 大丰市| 迁安市| 尚志市| 井冈山市| 许昌市| 湖口县| 清远市|