第四章 實驗設計與結果分析
4.3 實驗二:指令選取的比較
在此實驗,我們要比較的是以BURS 為基礎的指令選取機制和以 GLR Parser 為基礎的指令選取機制能否找出相同的解。
4.3.1 實驗設計
在將我們GLR Parser 整合到 CVM 的即時編譯器之後,我們就挑選幾個測試 檔來做實驗。一個Java 原始程式轉成 bytecodes 再轉成 Intermediate Representation 時,其實Intermediate Representation 是由一連串的樹所組成的,每個樹的大小不 一,而且多數的樹在交由我們GLR Parser 依照即時編譯器的指令文法去剖析時 並不會讓剖析過程中有兩個以上的剖析堆疊的存在,如此的IR tree 就不能被我 們GLR Parser 所使用。因此,為了讓我們 GLR Parser 在處理某個樹所轉成的字 串之後可以讓Graph-Structure Stack 中有許多的剖析堆疊存在,我們先研究了即 時編譯器的指令文法,找出是哪些規則的什麼特色造成了shift/reduce conflict 或 reduce/reduce conflict 的情況,以方便我們設計 Java 程式。
在我們所使用的即時編譯器的指令文法中,共有 195 條規則,而在交由 NewBison 當作輸入後,可發現共含有 155 個 shift/reduce conflict 和 1587 個 reduce/reduce conflict,而很多衝突都是發生在一個稱作 ICONST_32 的 terminal 身上,因此當我們GLR Parser 依照此模糊的指令文法去剖析一個由 IR tree 轉成 的字串時,要能在剖析過程中有多個剖析堆疊存在,則該IR tree 必須含有多個 ICONST_32 節點。而為了要得到這樣的 Intermediate Representation,我們在設計 Java 原始程式,就必須含有許多的常數運算。
Table 4.2 列出了挑選出來會交由我們 GLR Parser 來處理的測試檔,每個測 試檔是從其相關的Java 原始程式碼所轉成的樹狀 Intermediate Representation 的一 連串樹中選出的一個樹,而這個樹能夠讓我們GLR Parser 在處理時會有多個剖 析堆疊存在。第一個測試檔和第二個測試檔都是來自由Java 程式碼所撰寫的矩 陣乘法,所處理的兩個矩陣是16*16 大小。第一個測試檔僅有偏少的 12 個節點,
但仍然拿來做測試,主要是因為GLR Parser 在剖析它的過程中會遭遇到 shift/reduce conflict,而第二個測試檔則是我們找到具有最多節點的一個 Intermediate Representation,GLR Parser 若剖析它會遭遇到最多個數的
reduce/reduce conflict。第三個測試檔則是來自最小擴張樹演算法中的 Kruskal 演 算法,所使用的圖有13 個節點,21 個邊。第四個測試檔則是來自最大訪客數演 算法,計算有21 位訪客的情形。第五個測試檔則是大數乘法,計算兩個 7 位數 字的乘積。
Number of parse stacks in
the GSS 就是GLR Parser 在執行剖析 Intermediate Representation 時,會需要大量的運算,
最終才能找出最佳的指令序列,而BURS 卻是將許多的計算放在建立 tree automaton 表格時,因此在執行剖析 Intermediate Representation 只需要查表格就 可以找出最佳的解。因此若不能減少GLR Parser 在剖析時所需的計算,則指令 選取過程所需的時間會比BURS 來得多。能夠減少 GLR Parser 執行剖析時間的 一個方式就是減輕其Graph-Structure Stack 的負擔。第二點要克服的困難在於 GLR Parser 目前僅能剖析由 IR tree 轉成的 IR 字串,卻無法剖析由 IR DAG 轉成 的IR 字串,因此剖析後的結果會有重複的指令出現。