annotate paper/chapter4.tex @ 84:dbc35db820b4

tweak
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Mon, 18 Feb 2019 21:34:48 +0900
parents 7e50d0abefba
children 3bab40636107
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
60
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
1 \chapter{CbCによるMoarVM}
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 \section{スクリプト言語のバイトコード}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 プログラミング言語処理系は一般的に、 コンパイラ又はインタプリタに、 対象のソースコードを入力として与える。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 処理系はソースコード中の各文字列を、 トークンと呼ばれる形式に変換する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 トークンは処理系によってはオブジェクトそのものなどに変換される。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 このトークンに変換するフェーズを字句解析と呼ぶ。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 変換されたトークンが、 対象のプログラミング言語の文法などに沿っているかどうかの確認を行う。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 文法に沿っていた場合、 文法に応じてトークンを木構造に変換する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 これを構文解析と呼ぶ。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 構文解析の後は、 素朴なインタプリタ言語と呼ばれる種類のプログラミング言語の場合、 これらを木構造の根から順次実行する。
43
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
11 この処理の流れを図\ref{fig:not_use_bytecode_Sample_generally_lang}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
12 直接構文木を実行する場合、 実装そのものは単純になるが、 処理時間などが非常にかかるなどの特徴がある。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13
43
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
14 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
15 \caption{構文木を直接実行するプログラミング言語の処理の流れ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
16 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
17 \includegraphics[width=120mm]{./fig/not_use_bytecode_sample_generally_lang.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
18 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
19 \label{fig:not_use_bytecode_Sample_generally_lang}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
20 \end{figure}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
21
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 現在の主流なスクリプト言語は、 一旦変換した構文木をバイトコードと呼ばれるバイナリ形式に変換する。
43
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
23 バイトコードを利用する種類のプログラミング言語の、 処理の流れを図\ref{fig:bytecode_Sample_generally_lang}に示す。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 この場合、 入力されたソースコードをバイトコードに変換する実装と、 変換されたバイトコードを評価する仮想機械に処理系が分けられる。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 仮想機械はOSのエミュレータではなく、 プロセス仮想マシンと呼ばれるものである。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 バイトコードを直接出力できる形式のプログラミング言語にJava、 Javaの仮想機械にJVMが存在する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 内部的に利用しており直接は出力されない言語に、C言語で実装された MRIと呼ばれるrubyの実装などがあり、 この仮想機械にYARVが存在する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 バイトコードを経由することで、 コンパイルを担当する実装と、 評価を担当する仮想機械の実装に分類する事が可能となり、 それぞれに適した最適化処理が実装可能となる。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 また実行する際の速度もバイトコードを経由することで上昇する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30
43
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
31 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
32 \caption{バイトコードを使用するプログラミング言語の処理の流れ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
33 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
34 \includegraphics[width=120mm]{./fig/bytecode_sample_generally_lang.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
35 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
36 \label{fig:bytecode_Sample_generally_lang}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 40
diff changeset
37 \end{figure}
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 RakudoではPerl6、 NQPがそれぞれ対象のVMのバイトコードを生成し、 そのバイトコードをVMが実行する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 バイトコード生成までの処理をフロントエンドと呼び、 バイトコードから評価を行う処理をバックエンドと呼ぶ。
51
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
41 これらはJavaの様にバイトコードを出力する事も可能であるが、 オプションで指定しない限りは、 rubyなどの様に内部的にのみバイトコードを利用する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
42 主にRakudoで利用されている仮想機械にC実装のMoarVMがあり、 本研究ではMoarVMのバイトコード評価部分について検討をする。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 \section{オリジナルのMoarVMの処理}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 CbCでMoarVMを書き換える際に、 いきなり全てを実装する事は難しい。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 スクリプト言語の処理系の中心は、 与えられたバイトコードから実際の処理を逐次実装する部分である。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 その部分をバイトコードインタプリタと呼ぶ。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 今回はMoarVMの書き換えを検討する為に、 まずMoarVMのバイトコードインタプリタ部分の書き換えを行う。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 書き換えを行うにあたり、 MoarVMのオリジナルの箇所の実装を確認する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 今回対象とするMoarVMのバージョンは2018.04.01である。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
52 MoarVMのバイトコードは、 フォーマットが決まっており、 複数の意味のあるバイトコードの集合となっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
53 今回は、MoarVMの命令を実行する際に必要な、 命令コードに対応するバイトコードの部分に着目する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
54 これは、 今回書き換えを検討するMoarVMバイトコードインタプリタが読み込み、 評価するバイトコードの部分が、 命令コードバイトコードに対応する為である。
44
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
55 MoarVMのバイトコードの中の、 命令に対応するバイトコードの構成を図\ref{fig:bytecode_segment}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
56
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
57 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
58 \caption{MoarVMの命令バイトコード}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
59 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
60 \includegraphics[width=120mm]{./fig/bytecode_segment.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
61 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
62 \label{fig:bytecode_segment}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
63 \end{figure}
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
65
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
66 MoarVMの命令バイトコードは16ビットである。上位8ビットが、 バンクと呼ばれる命令セットの指定となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
67 MoarVMの命令はバンクの0から127番までが、 MoarVMのコア機能となっており、 128から255番までが、 拡張可能な命令セットとなっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
68 下位8ビットは、 バンクの内部の命令指定となっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
69 命令によっては、 この後のバイトコードで0個以上のオペランドを必要とする物がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
70 オペランドの中にはレジスタの型指定、 引数などが埋め込まれ、 命令バイトコードとの対応のために16ビットで表現される。
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
71
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
72
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
73 MoarVMのバイトコードインタプリタはsrc/core/interp.c中の関数 MVM\_interp\_runで定義されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
74 この関数ではMoarVMのバイトコードの中の、 命令に対応するバイトコードを解釈する。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 関数内では、 解釈するべきバイトコード列が格納されている変数 cur\_op や、現在と次の命令を指し示すop、 命令に対して受け渡す現在のVM情報であるThreadContex tcなどが変数として利用されている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 実際に命令ディスパッチを行っている箇所の一部をソースコード\ref{origin_dispatch}に示す。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 \lstinputlisting[frame=lrbt, label=origin_dispatch, caption=オリジナルのMoarVMの命令ディスパッチ部分]{./codes/src/dispatch.c}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 ソースコード\ref{origin_dispatch}中のOP(.*)と書かれている部分が、 それぞれのバイトコードが示す命令名となっている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 例えばno\_opは、 何もしない命令であるため、 マクロNEXTを利用しプログラムカウンタ相当のcur\_opを進めるのみの処理を行う。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
82 また登場する DISPATCH や OP 、 NEXT などはそれぞれマクロとして定義されている。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 これらMoarVM\_interp\_run中で、 利用されるマクロの定義を、 ソースコード\ref{origin_dispatch_macro}に示す。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 \lstinputlisting[frame=lrbt, label=origin_dispatch_macro, caption=オリジナルのMoarVM\_interp\_runで使用されるマクロ]{./codes/src/orig_macro.c}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
87 このマクロの中では、 利用しているCコンパイラがラベルに対してのgotoが利用できるコンパイラ拡張を実装している場合は MVM\_CGOTOが真となり、 6行目までが実行される。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 それ以外の場合は8行目以降のマクロ定義となる。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 ラベルgotoが利用できる場合、 マクロDISPATCHは空白として設定され、 マクロOPは、 それぞれの命令に対応したラベルとなる。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
90 この場合の処理の流れを図\ref{fig:origin_label_goto}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
92 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
93 \caption{ラベルgotoが利用できる場合のオリジナルのMVM\_interp\_runの処理の流れ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
94 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
95 \includegraphics[width=50mm]{./fig/origin_label_goto.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
96 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
97 \label{fig:origin_label_goto}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
98 \end{figure}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
99
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 次の命令に移動する際は、 マクロNEXT\_OPを用いてcur\_opを次の命令に移動させ、 opの値を再設定する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 このopが実行すべき命令の番号が格納されている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 opを用いて、ソースコード\ref{labels_list}に示す配列LABELSから、 命令に対応するラベルを取得する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 LABELSはマクロOPが変換したラベルのリストである。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
104 ソースコード\ref{origin_dispatch}の場合、no\_opはopが0が代入され、 const\_i8は1が設定されている。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 \lstinputlisting[frame=lrbt, label=labels_list, caption=MoarVMの命令ラベルが設定されている配列]{./codes/src/oplabels.h}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 ラベルgotoが利用できない場合、 マクロDISPATCHはswitch文に、 OPはcase文にそれぞれ変換される。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 cur\_opは数値そのものである為、 この場合はラベル配列へのアクセスは行われない。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
111 case文に変換された場合の処理の流れを\ref{fig:origin_not_use_label_goto}に示す。
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
113 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
114 \caption{case文に展開された場合のオリジナルのMVM\_interp\_runの処理の流れ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
115 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
116 \includegraphics[width=70mm]{./fig/origin_not_use_label_goto.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
117 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
118 \label{fig:origin_not_use_label_goto}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
119 \end{figure}
40
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 またソースコード\ref{origin_dispatch}の中に含まれているマクロGET\_REGは、 ソースコード\ref{get_reg_c}に示す定義がされている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 \begin{lstlisting}[frame=lrbt,label=get_reg_c,caption=レジスタ情報を取得するマクロGET\_REG]
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 #define GET_REG(pc, idx) reg_base[*((MVMuint16 *)(pc + idx))]
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 \end{lstlisting}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 配列reg\_baseはMoarVM上で利用される、 MoarVMのレジスタのリストである。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 このマクロ中のpcは、 MVM\_interp\_run上ではcur\_opとなっている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 idxは命令ごと個別に設定しており、 例えばconst\_i64内で利用されている GET\_REGは、 idxの値が0に設定されている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 これはMoarVMがレジスタ情報を取得する際に、 命令を基本に前後に参照できるレジスタを指定出来る為である。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 参照しているレジスタ集合の変数reg\_baseは、 MVM\_interp\_run中ではローカル変数として宣言されている。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 MoarVMのディスパッチ部分は、case文に変換される可能性がある。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 従って、 MoarVMの命令コードに対応する処理は、 Cソースファイルの特定の場所に記述せざるを得ない。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 この方法の場合、命令コードに対応する処理のファイル分割などのモジュール化が行えず、 1ファイル辺りの記述量が膨大になってしまう。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 \section{CbCによるMoarVMの実装}
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 interp.c内のMVM\_interp\_runでは、 命令コードのディスパッチはマクロを利用したcur\_opの計算及びラベルgoto、 もしくはマクロDISPATCHによるswitch-case文で行っていた。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 このディスパッチ方法では、 case文を利用する可能性があるため、 ファイルが冗長になる事や、 モジュール化が出来ないという問題が生じる。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 CbCによって書き換えを行ったMoarVMである、 CbCMoarVMではこの問題を解決する為に、 CodeGearの概念を導入する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 まず、 MoarVMの命令に対応するCodeGearを作成し、 各CodeGearの名前を要素として持つCbCのCodeGearテーブルを作成した。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 CodeGearのテーブルは、 特定のcbc\_nextというCodeGearから参照する。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 cbc\_nextから命令ごとのCodeGearに遷移し、 命令に対応する処理をした後に、 cbc\_nextに戻り、 別の命令に対応するCodeGearに遷移を繰り返す。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 このcbc\_nextは、 元のMVM\_interp\_runで使用されているマクロNEXTを、 CodeGearで書き直したものである。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 実際に書き直したマクロ及び、 cbc\_nextをソースコード\ref{cbc_next}に示す。
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149
1a2ad6e083bb add chapter4.tex
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 \lstinputlisting[frame=lrbt, label=cbc_next, caption=cbc\_next及びCbCMoarVMでのマクロ例]{./codes/src/cbc-interp-next.cbc}
47
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
152 CodeGear間の軽量継続を中心に設計している為、 switch case文を利用するマクロは削除した。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
153 また各マクロの引数に変数iを導入している。
47
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
154 変数i は、 バイトコードインタプリタ内で利用する、 MoarVMのレジスタ情報などが格納された、 構造体へのポインタである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
155 iが示す構造体INTER、 呼び i の型である構造体INTERPは、 ソースコード\ref{cbc_inter}の示すように宣言している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
156 これは、マクロ内部で現在の命令を示すopや、 命令列 cur\_op にアクセスする必要があるが、 従来のマクロの記述ではCbCを利用した場合に、変数にアクセス出来なくなる為に導入している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
157
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
158 \lstinputlisting[frame=lrbt, label=cbc_inter, caption=MoarVMの情報を格納した構造体INTER]{./codes/src/INTERP.h}
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
159
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
160 \section{命令実行箇所のCodeGearへの変換}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
161
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
162 命令実行箇所は、 case文又はラベルgotoで移動した先に記述されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
163 これらの箇所を、 それぞれ専用のCodeGearに変換することで、 命令の実行をCodeGearの遷移としてCbCを利用して実装する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
164 MVM\_interp\_runでは、 ソースコード\ref{origin_dispatch}中で示すとおり、 マクロOPを用いて記述されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
165
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
166 OPを用いて記述しているそれぞれの命令は、 通常ソースコード\ref{labels_list}に示すラベル配列、 またはswitch case文で遷移する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
167 従来はソースコード\ref{origin_dispatch_macro}に示す、 変数opの値利用してをマクロNEXTで対象の命令のラベル、 およびswitch文に値を引き渡す処理をしていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
168 CodeGearでの実装の際も、 このインターフェイスに揃えて実装する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
169 変数opの数値は、 ソースコード\ref{labels_list}に示すラベル配列の、 命令の登場順と対応している。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
170 その為命令を変換したCodeGearをラベル配列と順序を対応させ、 CodeGearの配列を作成する。
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
171 順序さえ対応させれば、 CodeGearの名前などは問わない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
172 実際に作成したCodeGearのリストをソースコード\ref{codegear_list}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
173 変換したCodeGearは、それぞれCodeGearであることを示す為、 接頭辞としてcbc\_を付けている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
174
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
175 \lstinputlisting[frame=lrbt, label=codegear_list, caption=CodeGear配列の一部]{./codes/src/oplables-cbc-codes.h}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
176
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
177 変換された各命令に対応するCodeGearの一部を、 ソースコード\ref{cbc_interp}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
178 このCodeGearはソースコード\ref{origin_dispatch}と対応している
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
179
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
180 \lstinputlisting[frame=lrbt, label=cbc_interp, caption=CbCMoarVMのバイトコード命令に対応するCodeGear]{./codes/src/cbc_codesegs.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
181
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
182 各CodeGearは入出力として構造体INTERのポインタを利用する。
50
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
183 これは、各命令の中で使用している cur\_op や tcなどの変数へのアクセスの為である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
184 通常のMoarVMの場合、 MVM\_interp\_runの関数内でタグgotoや、 switch文を利用する為に、 MVM\_interp\_runのローカル変数に各命令処理の中でアクセスする事が可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
185 しかし、 CbCMoarVMの場合、 MVM\_interp\_runから軽量継続を利用し、 CodeGearに遷移してしまう為、 これらローカル変数にアクセスできない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
186
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
187
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
188 作成したCodeGearのリストCODESは、 ソースコード\ref{cbc_next}に示すとおり、 cbc\_nextというCodeGearのみが取り扱う。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
189 cbc\_nextはマクロNEXTを利用しているが、 マクロNEXTはCODESにアクセスし、 対象となるCodeGearの名前を取得する。
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
190 CodeGearを取得後、 引数としてiを渡しgoto文によって命令ごとのCodeGearに遷移する。
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
191
50
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
192 命令ディスパッチに関するCodeGearの状態遷移図を図\ref{fig:dispatch_cbc}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
193
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
194 \begin{figure}[ht]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
195 \caption{CbCMoarVMの命令バイトコードディスパッチの状態遷移}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
196 \begin{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
197 \includegraphics[width=120mm]{./fig/cbc_next.pdf}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
198 \end{center}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
199 \label{fig:dispatch_cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
200 \end{figure}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
201
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
202 図中の破線部分は通常のC言語の関数呼び出しが行われる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
203 CodeGearからCの関数呼び出しの返り値を利用することなどは通常のC言語と同様に可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
204 各命令に対応したCodeGearは、 cbc\_next から遷移し、 処理を行った後 cbc\_next にgoto文で軽量継続する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
205
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
206 また、 変換した命令の中には switch case文での、 breakが発生せず、 次のcase文に移行する命令が存在する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
207 各CodeGearは1命令に閉じてしまっている為、 cbc\_next ではなく、 明示的に次に次のCodeGearを指定する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
208 今回は直接 CodeGear 中に遷移先のCodeGearをgoto文を付けて記述した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
209 ソースコード\ref{cbc_interp}中では、 cbc\_const\_i8などが該当する。
51
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
210
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
211
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
212 命令の数は膨大である為、 全てを手作業で変換するのは望ましくない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
213 本研究ではPerlスクリプトを用いて、 interp.c から命令をCodeGearにそれぞれ変換し、 CodeGearのリストを自動的に作成するスクリプトを作成した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
214 このスクリプトは以下の修正手続きを実行する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
215
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
216
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
217 \begin{itemize}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
218 \item OP(.*)の.*部分をCodeGearの名前として、 先頭にcbc\_をつけた上で設定する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
219 \item cur\_opなど、 構造体INTERのメンバ変数は、 ポインタiから参照するように修正する。
52
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
220 \item GC対策のためマクロMVMROOTを利用している箇所は、 一度ダミーの関数を経由する。
51
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
221 \item 末尾のgoto NEXTをgoto cbc\_next(i)に修正する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
222 \item case文で下のcase文に移行する箇所は、 case文に対応するCodeGearに遷移する様にgoto文を付け加える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
223 \end{itemize}
52
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
224
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
225 この中の MVMROOT をソースコード\ref{MVMROOT}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
226
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
227 \begin{lstlisting}[frame=lrbt,label=MVMROOT,caption={MVMROOTの定義}]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
228 /* Macros related to rooting objects into the temporaries list, and
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
229 * unrooting them afterwards. */
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
230 #define MVMROOT(tc, obj_ref, block) do {\
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
231 MVM_gc_root_temp_push(tc, (MVMCollectable **)&(obj_ref)); \
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
232 block \
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
233 MVM_gc_root_temp_pop(tc); \
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
234 } while (0)
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
235 \end{lstlisting}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
236
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
237 MVMROOTは、 行いたい処理の前後で、MVM\_gc\_root\_temp系統のpushとpopのスタック操作の関数を実行する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
238 これは、 MoarVMが所持しているガベージコレクションに、 行いたい処理の間にオブジェクトが回収されるのを防ぐための処理である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
239 ガベージコレクションの回収を防ぐために、 MVM\_gc\_root\_temp\_pushでは、 大域変数の配列に一時的にオブジェクトのアドレスを入れる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
240 このオブジェクトは、 CodeGear中のローカル変数であるが、 CodeGear中のローカル変数は通常別のCodeGearに移動する際に破棄する為、 この様な動きを想定していない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
241 その為、 MVMROOT を呼び出す処理の場合は、 MVMROOT を使う命令を別の関数でラップし、 CodeGearから関数呼び出しの形で命令を呼び出す。
60
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
242
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
243
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
244
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
245 \section{MoarVMのデバッグ}
60
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
246 CbCで書き換えたMoarVMであるCbCMoarVMは、 現在gcc、 LLVM/clang上に実装しているCbCコンパイラでビルドする事が可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
247 また、 それぞれO3までの最適化オプションをビルド時に指定してもビルドする事が可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
248
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
249 MoarVMの書き換えに伴って、 正常にオリジナルのMoarVMと同じ振る舞いをするか確認をしたい。
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
250 MoarVM自体には現在テストコードが存在しない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
251 MoarVMのリポジトリ内のメッセージには、MoarVM上で動作するNQP、 及びRakudoに付随しているテストコードで、 MoarVMの実装をテストする事が推奨されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
252 NQPやRakudoのテストは、 ソースコード\ref{cbc_test_nqp}に示す様なコードを利用する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
253 実際にNQPとPerl6のインタプリタとしてビルドした、 nqpやperl6コマンドを実行する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
254 実行時に出力された結果と、 期待する結果が一致するかを確認する方式である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
255
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
256 \lstinputlisting[frame=lrbt, label=cbc_test_nqp, caption=NQPのテストコードの例]{./codes/test.nqp}
60
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
257
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
258 NQPやRakudoのテストを行うには、セルフビルドしたそれぞれのインタプリタであるnqp、 perl6を作らなければならない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
259 しかし、 これらをビルドする際にはMoarVMの実行バイナリである moar を動かす必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
260 nqpなどのビルド時には、 入力として与えられたバイトコードを解析し、 命令部分をディスパッチするバイトコードインタプリタを使用せざるを得ない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
261 今回はバイトコードディスパッチ部分を書き換えた為、 この部分にバグが生じていると、 そもそもnqpやperl6を生成する事が出来ない。
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
262 その為、 利用したいnqpやperl6のテストコードを出力を通して確認する事が出来ない。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
263 従って今回はMoarVM自体にバイトコードを入力として与え、 期待する動作をするかどうかを独自に確認する必要がある。
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
264
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
265
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
266 \section{CbCMoarVMのデバッグ}
62
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 61
diff changeset
267 CbCMoarVMが正常にバイトコードを実行しているかどうかは、 正常に動くオリジナルのMoarVMと、 実行したバイトコードの差分を検知することで確認する事が可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 61
diff changeset
268 入力として与えたスクリプトは常に同じバイトコードに変換されると考えられるが、 MoarVMはバイトコードにUUIDの様な物を埋め込んでしまう為、 同じファイルを与えても生成されるバイトコードが異なってしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 61
diff changeset
269 その為、 NQPインタプリタのREPLの様な機能を使い、 それぞれのVMが同じ命令から処理を開始する様に調整する。
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
270
62
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 61
diff changeset
271 差分は、 バイトコードインタプリタのMVM\_interp\_runのソースコード中で、 次の命令を計算する箇所で、 命令に対応する数値を出力する様に付け加える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 61
diff changeset
272 その出力を、 gdbなどのデバッガとscriptコマンドなどを用いてログを取り、 perlなどのスクリプトを用いて解析する。
61
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
273 実際に差分を確認したスクリプトの実行結果の一部を、 ソースコード\ref{cbc_origin_diff}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
274
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
275 \lstinputlisting[frame=lrbt, label=cbc_origin_diff, caption=MoarVMとCbCMoarVMの実行命令の差分検知]{./codes/diff.txt}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
276
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
277 左行がオリジナルのMoarVMの実行命令であり、 右行がCbCMoarVMの実行命令である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
278 出力している命令番号は、 それぞれLABELやCODESなどの命令リストの配列の番号と対応している為、 対応するCodeGear名を同時に出力している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
279 $\ast$が先頭に付随する行で差異が発生しており、 それぞれ実行している命令の番号が異なる事が確認出来る。
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
280 この例ではオリジナルのMoarVMは invoke\_o 命令を実行しているのに対し、 CbCMoarVMでは takeclosure 命令を実行している。
63
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
281
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
282 \section{CbCMoarVMの現在の実装}
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
283
82
7e50d0abefba remove ,...
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
284 CbCMoarVMは現在Perl6のサブセットであるNQP、 NQPで書かれたPerl6のビルドに成功している。
63
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
285 各言語のインタプリタであるnqp、 perl6共に、 CbCMoarVMの実行バイナリを利用して動作する。
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
286
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
287 デバッグ時の利便性などから、 現在はオリジナルのバイトコードインタプリタ部分を実行するか、 CbCで記述されたバイトコードインタプリタを実行するかをオプションを通して選択可能となっている。
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
288
71c44ceda013 update chapter4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 62
diff changeset
289 またそれぞれのテストコードは、 移植元のMoarVMと同等のテスト通過率を示している。