Mercurial > hg > Papers > 2019 > anatofuz-thesis
changeset 53:1499d4fbbb31
update
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 16 Feb 2019 13:55:01 +0900 |
parents | 2e43fd532f89 |
children | dc67d629bdd9 |
files | paper/main.pdf prepaper/finalpre.pdf prepaper/finalpre.tex prepaper/pic/cbc_next.pdf prepaper/pic/perl6nqp.pdf prepaper/pic/stagenqp.pdf prepaper/pic/tgraph.pdf prepaper/src/cbc_codesegs.cbc prepaper/src/cbc_example.cbc prepaper/src/dispatch.c prepaper/src/tgraph.graffle |
diffstat | 11 files changed, 160 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/prepaper/finalpre.tex Fri Feb 15 21:16:25 2019 +0900 +++ b/prepaper/finalpre.tex Sat Feb 16 13:55:01 2019 +0900 @@ -19,6 +19,33 @@ \setlength{\footskip}{0mm} \pagestyle{empty} +\usepackage{comment} +\usepackage{listings} +\lstset{ + language=C, + tabsize=2, + frame=single, + basicstyle={\ttfamily\footnotesize}, % + identifierstyle={\footnotesize}, % + commentstyle={\footnotesize\itshape}, % + keywordstyle={\footnotesize\bfseries}, % + ndkeywordstyle={\footnotesize}, % + stringstyle={\footnotesize\ttfamily}, + breaklines=true, + captionpos=b, + columns=[l]{fullflexible}, % + xrightmargin=0zw, % + xleftmargin=1zw, % + aboveskip=1zw, + numberstyle={\scriptsize}, % + stepnumber=1, + numbersep=0.5zw, % + lineskip=-0.5ex, +} +\renewcommand{\lstlistingname}{ソースコード} +\usepackage{caption} +\captionsetup[lstlisting]{font={small, tt}} + \input{dummy.tex} \renewcommand{\abstractname}{Abstract} \begin{document} @@ -90,12 +117,104 @@ % \label{fig:tree} %\end{figure} -\section{Continuation based C (CbC)} -CbC は 処理を Code Gear とした単位を用いて記述するプログラミング言語\cite{kaito:2015}である。 -Code Gear は入力と出力を持ち、CbC では引数が入出力となっている。 -Code Gear から次の Code Gear へと goto による継続で遷移で処理を行い、引数として出力を与える。 -図\ref{fig:cs}は Code Gear 間の処理の流れを表している。 +\section{CbC} +Perl6処理系の改良にはgccとLLVM/Clang上に実装したContinuation based C(CbC)を用いる. +CbCはCodeGearを基本的な処理単位とし,CodeGearの遷移でプログラムを記述するCの下位言語である. +CodeGearの宣言は\_\_codeという型を持つ関数として宣言する. +\_\_codeは内部的にはvoid型として扱っているが,プログラマからの扱いはCodeGearである事を示す指示子のような役割である. +CodeGearはCの関数とは異なり返り値を持たず,呼び差し元の関数に戻る代わりに別のCodeGearへ遷移する. +CbCにおけるCodeGear間の継続はスタックに値を積まず,環境も遷移時に持たない為軽量継続と呼ぶ. +CbCは軽量継続を中心にプログラミングする事が可能であるため,レジスタの移動などが行われない. +その為並列化やループ制御,関数呼び出しにおけるスタック制御などを意識したプログラミングスタイルでプログラミングする事が可能である. +\lstinputlisting[label=cbcexample, caption=cbc\_example.cbc]{src/cbc_example.cbc} + + + +\section{Perl6} +Perlの現在の主流な実装はRakudoである.RakudoはMoarVM,とNQPと呼ばれるPerl6のサブセット,NQPで記述されたPerl6という構成である. +MoarVMはNQPを解釈する. +このNQPで記述されたPerl6の事をRakudoと呼ぶ. +RakudoはMoarVMの他にJVM,Javascriptを動作環境として選択可能である. +言語的な特徴ではPerl5とは違いオブジェクト指向のサポートが強力になり,漸進的型付け言語としての特徴を持つ. + +%処理時間は状況にもよるが231Kbのファイルを正規表現で検索する例題を実行した場合 +処理時間は状況によるが,231KBのファイルを正規表現で検索する例題の場合Perl5が0.04sに対しMoarVMに乗せたPerl6は0.86sとおよそ20倍の速度差がある. +%* Perl5 +% * 0.04s +%* Ruby +% * 0.15s +%* Python +% * 0.06s +%* Java +% * 0.27s +%* Perl6(Moar) +% * 0.86s + +\section{NQP} +NQPとはPerl6のサブセットである. +その為基本的な文法などはPerl6に準拠しているが,変数を束縛で宣言するなどの違いが見られる. + +NQPは最終的にはNQP自身でブートストラップする言語であるが,ビルドの最初にはすでに書かれたMoarvMByteCodeを必要とする. +このMoarVMByteCodeの状態をStage0と言う. +Perl6の一部はNQPを拡張したもので書かれている為,Rakudoを動作させる為にはMoarVMなどのVM,VMに対応させる様にビルドしたNQPがそれぞれ必要となる. +NQPは与えられたStage0を使いStage1をビルドし,そのStage1を利用しStage2をビルドする事で生成できる. +\section{MoarVM} +MoarVMはPerl6に特化したVMである.C言語で実装されている. +JITコンパイルなどが現在導入されているが,起動時間などが低速である問題がある. +MoarVM独自のByteCodeがあり,NQPからこれを出力する機能などが存在している. +%Perl6のコンパイルの流れをT図 (図\ref{perl6buil})に示す. +% IT図をいれる +\begin{figure}[ht] + \begin{center} + \includegraphics[width=65mm]{pic/tgraph.pdf} + \end{center} + \caption{Perl6のビルドフロー} + \label{fig:perl6buil} +\end{figure} + + +\section{MoarVMのディスパッチ} +MoarVMはNQPから変換されたバイトコードを読み取り,都度実行する. +MoarVMの場合この処理はMVM\_interp\_runという関数で行われている. +この関数内ではMoarVMが実行すべき命令が並んだ命令列を持ち,その値で巨大なcase文,またはCのラベルジャンプによって分岐させる. +分岐後は命令に応じた処理をMoarVMが行い,次の命令を実行する. +分岐後は命令にごとの処理を実行し,現在の命令列から,実行した命令の長さ分命令列を進める. +進めた後にcase文の先頭もしくはCのラベルジャンプを利用して次の処理に遷移する. +これを命令コードのディスパッチと呼ぶ. +命令コードの実行の中では,現在のMoarVMのレジスタであるreg\_baseやスレッドごとの環境である構造体tcなどを参照する. +この方法の問題点として,巨大なcase文になっている為命令列の分割が出来ない. +ディスパッチ部分の処理が都度走る為低速になる. +Cファイルでの可読性とモジュール化が損なわれてしまう. +ラベルにbreak pointを設定できない為デバッグし辛いなどがあげられる. +\lstinputlisting[label=origdis, caption=MoarVM内のインタプリタのディスパッチ]{src/dispatch.c} + +\section{CbCMoarVMのディスパッチ} +本研究ではMoarVMは2018.04.01のバージョンで実装している. +命令コードの実行すべき単位はCbCのCodeGearの単位として扱える為命令処理をCodeGearに変換する. +変換されたCodeGearはオリジナルのMoarVMの命令コードと対応させる為にCodeGearの配列に格納する. +MoarVMはこの配列を参照し,要素として得られるCodeGearに軽量継続を行う. +CodeGearでの処理が終了すると,次のCodeGearを決定する為に必要な計算をcbc\_nextというCodeGearで行い,次の命令列に軽量継続する. +\lstinputlisting[label=codeseg, caption=CbCMoarVM内のインタプリタの状態遷移]{src/cbc_codesegs.cbc} + +\begin{figure}[ht] + \begin{center} + \includegraphics[width=50mm]{pic/cbc_next.pdf} + \end{center} + \caption{CbCにおけるMoarVMバイトコードインタプリタ内の状態遷移} + \label{fig:perl6cbcinter} +\end{figure} + + +オリジナルのMoarVMとは異なり,同一関数上で実行する訳では無い為,MVM\_interp\_runで定義している局所変数のレジスタreg\_baseなどにアクセスすることは通常では出来ない. +その為CodeGearの遷移において,これら必要なインタプリタの情報を纏めた構造体INTERを宣言し,このポインタであるINTERPを引数として入力する. +各CodeGearではこのINTERPを経由することでレジスタ情報などにアクセスする. + +この方法の利点としてCodeGearは単なる関数として扱える為,元のソースコードの様に同一ファイル内に全ての処理を書く必要がない. +またラベルにはbreak pointを設定する事が出来なかったが,CodeGearはデバッガからは関数として見る事ができるため通常のCの関数の様にbreak pointを設定する事が可能である. + +このCbCMoarVMのデバッグにはオリジナルのMoarVMとCbCMoarVMが実行した命令コードをデバッガで出力しログを取る必要がある. +取得したログから実行すべき命令番号が設定されている変数opの値を,オリジナルとCbC版で違いが発生するか解析する. \section{今後の課題} 本研究では interface の記述、CbC ファイルから Gears OS の記述に必要な Context と stub の生成を行う perlスクリプトの生成を行なった。
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prepaper/src/cbc_codesegs.cbc Sat Feb 16 13:55:01 2019 +0900 @@ -0,0 +1,12 @@ +__code cbc_no_op(INTERP i){ + goto cbc_next(i); +} +__code cbc_const_i32(INTERP i){ + MVM_exception_throw_adhoc(i->tc, "const_iX NYI"); + goto cbc_const_i64(i); +} +__code cbc_const_i64(INTERP i){ + GET_REG(i->cur_op, 0,i).i64 = MVM_BC_get_I64(i->cur_op, 2); + i->cur_op += 10; + goto cbc_next(i); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prepaper/src/cbc_example.cbc Sat Feb 16 13:55:01 2019 +0900 @@ -0,0 +1,14 @@ +int main (){ + int data = 0; + goto cg1(&data); +} + +__code cg1(int *datap){ + (*datap)++; + goto cg2(datap); +} + +__code cg2(int *datap){ + (*datap)++; + printf("%d\n",*datap); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prepaper/src/dispatch.c Sat Feb 16 13:55:01 2019 +0900 @@ -0,0 +1,10 @@ +DISPATCH(NEXT_OP) { + OP(no_op): + goto NEXT; + OP(const_i32): + MVM_exception_throw_adhoc(tc, "const_iX NYI"); + OP(const_i64): + GET_REG(cur_op, 0).i64 = MVM_BC_get_I64(cur_op, 2); + cur_op += 10; + goto NEXT; +}