# HG changeset patch # User Takahiro SHIMIZU # Date 1543573346 -32400 # Node ID 1b1089b0aef508e892937fee57656beae9eed7d7 # Parent dec42afa6aaa03906f8584541160475267596312 update diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/anatofuz.pdf Binary file Paper/anatofuz.pdf has changed diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/anatofuz.tex --- a/Paper/anatofuz.tex Fri Nov 30 11:44:49 2018 +0900 +++ b/Paper/anatofuz.tex Fri Nov 30 19:22:26 2018 +0900 @@ -46,7 +46,8 @@ %概要 \begin{abstract} スクリプト言語であるPerl5の後継言語としてPerl6が現在開発されている. -Perl6は設計と実装が区分されており様々な処理系が開発されている.現在主流なPerl6はRakudoと言われるプロジェクトである. +Perl6は設計と実装が区分されており様々な処理系が開発されている. +現在主流なPerl6はRakudoと言われるプロジェクトである. RakudoではPerl6自体をNQP(NotQuitPerl)と言われるPerl6のサブセットで記述し, NQPをVMが解釈するという処理の流れになっている. このVMは任意のVMが選択できるようになっており,主に利用されているVMにCで書かれたMoarVMが存在する. MoarVMはJITコンパイルなどをサポートしているが, 全体的な起動時間及び処理速度がPerl5と比較し非常に低速である. @@ -87,7 +88,8 @@ \subsection{CbCの概要} CbCは当研究室で開発しているプログラミング言語である. Cレベルでのプログラミングを行う場合, 本来プログラマが行いたい処理の他にmallocなどを利用したメモリのアロケートやエラーハンドリングなどを記述する必要がある. -これらの処理をmeta computationと呼ぶ.これらmeta computationと通常の処理を分離することでバグの原因がmeta computation側にあるか処理側にあるかの分離などが可能となる. +これらの処理をmeta computationと呼ぶ. +これらmeta computationと通常の処理を分離することでバグの原因がmeta computation側にあるか処理側にあるかの分離などが可能となる. しかしC言語などを用いたプログラミングでmeta computationの分離を行おうとすると, それぞれ事細かに関数やクラスを分割せねばならず容易ではない. CbCでは関数よりmeta computationを細かく記述する為にCodeGearという単位を導入した. またCodeGearの実行に必要なデータをDataGearという単位で受け渡す. @@ -119,23 +121,24 @@ CbCは現在主要なCコンパイラであるgcc及びllvmをバックエンドとしたclang上の2種類の実装が存在する. gccはバージョン9.0.0に, clangは7.0.0に対応している. -\subsection{CbCコンパイラのバグ} -% 局所変数のポインタを握ったままgotoするとtail callにならない -CbCコンパイラは現在も開発中であり幾つかのバグが発見されている. -まずCodeGear内で宣言した局所変数のポインタを大域変数の配列などに保存した状態でgotoしてしまうとtail call最適化が無効となる. -これはただの関数呼び出しになってしまう為, 直接的な被害はないもののCbCとしての利点が損なわれてしまう. -%また本来は操作しないはずのスタック領域の操作が入ってしまうため, プログラマの意図と反したスタックポインタなのど操作が行われてしまいバグが発生する可能性が存在する. -また, CbCの挙動としてCodeGearへの遷移時には軽量継続を行う為スタック領域の操作は行われないはずである. -しかし, 現状は配列にCodeGearのアドレスを代入し, 間接的に軽量継続を行おうとすると, スタック領域の操作が通常の関数呼び出しの様に行われてしまう. -%これは一部CbCコンパイラが利用しているgcc側のref-zoneという機能が影響していたが - +%\subsection{CbCコンパイラのバグ} +%% 局所変数のポインタを握ったままgotoするとtail callにならない +%CbCコンパイラは現在も開発中であり幾つかのバグが発見されている. +%まずCodeGear内で宣言した局所変数のポインタを大域変数の配列などに保存した状態でgotoしてしまうとtail call最適化が無効となる. +%これはただの関数呼び出しになってしまう為, 直接的な被害はないもののCbCとしての利点が損なわれてしまう. +%%また本来は操作しないはずのスタック領域の操作が入ってしまうため, プログラマの意図と反したスタックポインタなのど操作が行われてしまいバグが発生する可能性が存在する. +%また, CbCの挙動としてCodeGearへの遷移時には軽量継続を行う為スタック領域の操作は行われないはずである. +%しかし, 現状は配列にCodeGearのアドレスを代入し, 間接的に軽量継続を行おうとすると, スタック領域の操作が通常の関数呼び出しの様に行われてしまう. +%%これは一部CbCコンパイラが利用しているgcc側のref-zoneという機能が影響していたが +% \subsection{CbCとCの互換性} CbCコンパイラはコンパイル対象のソースコードがCbCであるかどうかを判断する. この際にCodeGearを利用していない場合は通常のCプログラムとして動作する. その為今回検証するMoarVMのビルドにおいてもCbCで書き換えたソースコードがあるMoarVMと, 手を加えていないオリジナルのMoarVMの2種類を同一のCbCコンパイラでビルドする事が可能である. またCからCbCへの遷移時に, 再びCの関数に戻るように実装したい場合がある. -その際は環境付きgotoと呼ばれる手法を取る.これは\_CbC\_return及び\_CbC\_environmentという変数を使用する. +その際は環境付きgotoと呼ばれる手法を取る. +これは\_CbC\_return及び\_CbC\_environmentという変数を使用する. この変数は\_CbC\_returnが元の環境に戻る際に利用するCodeGearを指し, \_CbC\_environmentは復帰時に戻す元の環境である. 復帰する場合, 呼び出した位置には帰らず, 呼び出した関数の終了する位置に帰る. \lstinputlisting[label=cbcreturn, caption=環境付き継続の例]{./src/return.cbc} @@ -144,8 +147,8 @@ \subsection{言語処理系におけるCbCの応用} -CbCを言語処理系, 特にスクリプト言語に応用すると幾つかの箇所に置いて利点があると推測される. -CbCにおけるCodeGearはコンパイラの基本ブロックに相当する. +CbCを言語処理系, 特にスクリプト言語に応用すると幾つかの箇所に置いて利点がある. +CodeGearはコンパイラの基本ブロックに相当する. その為従来のスクリプト言語では主にcase文で記述していた命令コードディスパッチの箇所をCodeGearの遷移として記述する事が可能である. 通常の言語処理系では命令コードディスパッチ部分は巨大なcase文となり, この部分を実装したCファイルが巨大化してしまう. CodeGearを導入することで巨大なcase文をCodeGearとして分割する事が可能となり, 処理のモジュール化が可能となる. @@ -163,33 +166,35 @@ Perl5は設計と実装が同一であり, Larryらによって書かれたC実装のみだった. Perl6は設計と実装が分離している. 言語的な特徴としては, 独自にPerl6の文法を拡張可能なGrammar, Perl5と比較した場合のオブジェクト指向言語としての進化も見られる. -またPerl6は漸進的型付け言語である. +またPerl6は漸進的型付け言語である. 従来のPerlの様に変数に代入する対象の型や, 文脈に応じて型を変更する動的型言語としての側面を持ちつつ, 独自に定義した型を始めとする様々な型に, 静的に変数の型を設定する事が可能である. Perl6は言語仕様及び処理実装がPerl5と大幅に異なっており, 言語的な互換性が存在しない. 従って現在ではPerl6とPerl5は別言語としての開発方針になっている. Perl6は現在有力な処理系であるRakudoから名前を取りRakuという別名がつけられている. -\subsection{Rakudo以前の処理系} -Perl6の実装は様々なものが実装された. -まず2005年に唐鳳によってHaskellで実装されたPugs\cite{pugs}が登場した. - -その後Pythonとの共同動作環境としてParrot\cite{parrot}が実装された. -ParrotはPASMと呼ばれるバイトコードを解釈可能なレジスタマシンである. -ParrotでのPerl6の実装はNQP(NotQuitPerl)と呼ばれるPerl6のサブセットでPerl6を記述するというアイディアの基実装された. -ParrotVMは2006年のversion8.1.0が最後のリリースである. -こちらもPugsと同様に現在のPerl6プロジェクトでは歴史的な実装とされている. +%\subsection{Rakudo以前の処理系} +%Perl6の実装は様々なものが実装された. +%まず2005年に唐鳳によってHaskellで実装されたPugs\cite{pugs}が登場した. +% +%その後Pythonとの共同動作環境としてParrot\cite{parrot}が実装された. +%ParrotはPASMと呼ばれるバイトコードを解釈可能なレジスタマシンである. +%ParrotでのPerl6の実装はNQP(NotQuitPerl)と呼ばれるPerl6のサブセットでPerl6を記述するというアイディアの基実装された. +%ParrotVMは2006年のversion8.1.0が最後のリリースである. +%こちらもPugsと同様に現在のPerl6プロジェクトでは歴史的な実装とされている. \subsection{Rakudo} -RakudoとはParrotで構想に上がったNQP, NQPに基づくPerl6を基にしたプロジェクトである. + +RakudoとはNQP, NQPに基づくPerl6を基にしたプロジェクトである. +NQPとは, 以前のPerl6処理系であるParrot\cite{parrot}で, 構想に上がったPerl6のサブセットである. RakudoがPerl6のコンパイラかつインタプリタであると考えても良い. Rakudoは図\ref{fig:perl6construction}に示す構成になっている. Rakudoにおけるコンパイラとは厳密には2種類存在する. まず第1のものがPerl6, もしくはNQPをMoarVM, JVMのバイトコードに変換するNQPコンパイラである. 次にそのNQPが出力したバイトコードをネイティブコードに変換するVMの2種類である. -このVMは現在MoarVM, JavaVM, JavaScriptを選択可能である. +このVMは現在MoarVM, JavaVMを選択可能である. Rakudo及びNQP projectではこのNQPコンパイラの部分をフロントエンド, VMの部分をバックエンド\cite{rani1}と呼称している. NQPで主に書かれ, MoarVMなどNQPが動作する環境で動くPerl6のことをRakudoと呼ぶ. Perl6はNQP以外にもNQPを拡張したPerl6自身で書かれている箇所が存在し, これはNQPコンパイラ側でMoarVMが解釈可能な形へ変換を行う. @@ -202,14 +207,39 @@ \label{fig:perl6construction} \end{figure} +\subsection{MoarVM} +MoarVMとはRakudoで主に開発が進められているVMである. +Perl6及びNQPの専用処理系であり, レジスタマシンである. +MoarVMはNQPから与えられたMoarVMのバイトコードを実行する. + +MoarVMのバイトコードインタプリタはsrc/core/interp.cで定義されている. +この中の関数MVM\_interp\_runで命令に応じた処理を実行する. +関数内では命令列が保存されているcur\_op, 現在と次の命令を指し示すop, Threadの環境が保存されているThreadcontextなどの変数を利用する. +命令実行は大きく二種類の動作があり, Cのgotoが利用できる場合はCode\ref{orig_macro}に示すMVM\_CGOTOフラグが立ちラベル遷移を利用する. +goto文が利用できない場合は巨大なcase文として命令を実行する. + +ラベル遷移を利用する場合はCode\ref{oplabelsh}に示すラベルテーブルLABELSにアクセスし, テーブルに登録されているアドレスを取得し, マクロNEXTで遷移する. +Code\ref{dispatch_c}に示すno\_opは何もせず次の命令に移動する為, goto NEXT;のみ記述されている. + +\lstinputlisting[label=orig_macro, caption=interp.cのマクロ部分]{./src/orig_macro.c} +\lstinputlisting[label=oplabelsh, caption=ラベルテーブルの一部分]{./src/oplabels.h} + +\lstinputlisting[label=dispatch_c, caption=オリジナル版MoarVMのバイトコードディスパッチ]{./src/dispatch.c} + +%interp.cでは命令コードのディスパッチはマクロを利用したcur\_opの計算及びラベルの遷移, もしくはマクロDISPATCHが展開するswitch文で行われていた. +この為MoarVM内の命令コードに対応する処理は, 命令ディスパッチが書かれているCソースファイルの, 特定の場所のみに記述せざるを得ない. +その為命令コードのモジュール化などが行えず, 1ファイル辺りの記述量が膨大になってしまう. +また各命令コードに対応する処理は, ラベルジャンプもしくはswitch文に展開されてしまう為, Threaded Codeの実装を考えた場合, 大幅なコードの改修が要求される. +デバッグ時には, Cレベルでのデバッグ時にはアドレスと実際に呼ばれる箇所を確認する事に手間がかかる. + \subsection{NQP} -RakudoにおけるNQP\cite{nqp}は現在MoarVM, JVM上で動作し, MoarVMを一部利用することでNodeJSからも動作させる事が可能である. +RakudoにおけるNQP\cite{nqp}は現在MoarVM, JVM上で動作する. NQPはPerl6のサブセットであるため, 主な文法などはPerl6に準拠しているが幾つか異なる点が存在する. NQPは最終的にはNQP自身でブートストラップする言語であるが, ビルドの最初にはすでに書かれたMoarVMのバイトコードを必要とする. このMoarVMのバイトコードの状態をStage0と言う.%い, バイトコードが付随するソースディレクトリ内のディレクトリ名として設定されている. Perl6の一部はNQPを拡張したもので書かれている為, Rakudoを動作させる為にはMoarVMなどのVM, VMに対応させる様にビルドしたNQPがそれぞれ必要となる. -現在のNQPではMoarVM, JVMに対応するStage0はそれぞれMoarVMのバイトコード, jarファイルが用意されており, JavaScriptではバイトコードの代わりにランタイム独自のModuleLoaderなどが設計されている. +現在のNQPではMoarVM, JVMに対応するStage0はそれぞれMoarVMのバイトコード, jarファイルが用意されている. MoarVMのModuleLoaderはStage0にあるMoarVMのバイトコードで書かれた一連のファイルが該当する. @@ -222,7 +252,7 @@ \begin{figure}[ht] \begin{center} - \includegraphics[width=70mm]{fig/stagenqp.pdf} + \includegraphics[width=70mm]{fig/tgraph.pdf} \end{center} \caption{NQPのビルドフロー} \label{fig:nqpbuild} @@ -230,7 +260,8 @@ NQPのビルドフローを図\ref{fig:nqpbuild}に示す. RakudoによるPerl6に処理系はNQPにおけるnqpと同様に, moarにライブラリパスなどを設定したperl6というシェルスクリプトである. -このperl6を動かすためにはself buildしたNQPコンパイラが必要となる.その為にStage0を利用してStage1をビルドしNQPコンパイラを作成する. +このperl6を動かすためにはself buildしたNQPコンパイラが必要となる. +その為にStage0を利用してStage1をビルドしNQPコンパイラを作成する. Stage1は中間的な出力であり, 生成されたNQPファイルはStage2と同一であるが, MoarVMのバイトコードが異なる. Perl6では完全なセルフコンパイルを実行したNQPが要求される為, Stage1を利用してもう一度ビルドを行いStage2を作成する. @@ -238,19 +269,19 @@ 現在の公表されているNQPのオペコードはNQPのリポジトリ\cite{nqpopcode}に記述されているものである. -\subsection{Rakudo Perl6} -Rakudo実装上におけるPerl6はRakudo Perl6と呼ばれているGitリポジトリで管理されているプログラムのことである. -前述した通りRakudo Perl6はPerl6のサブセットであるNQPを用いて記述されている. -従ってyaccやlexと言ったPerl5の文字解析, 構文解析に利用していたプログラムは利用せず, NQP側で構文定義などを行っている. -NQPはNQP自身でBootstrappingされている為, Rakudo Perl6のbuild時にはNQPの実行環境として要したVM, それに基づいてbuildしたNQPがそれぞれ必要となる. - - - -\subsection{現在のPerl6} -Perl6の言語仕様\cite{perl6design}とその時点での実装状況をまとめた公式ドキュメント\cite{perl6doc}は分離している. -従来は言語仕様は自然言語の仕様書であったが, 現在はテストスイートであるRoast\cite{roast}そのものと定義されている. -現在のPerl6の仕様を読む場合Roastを確認し, 現在Rakudo上に実装されている機能を見る場合は公式ドキュメントを確認する必要がある. - +%\subsection{Rakudo Perl6} +%Rakudo実装上におけるPerl6はRakudo Perl6と呼ばれているGitリポジトリで管理されているプログラムのことである. +%前述した通りRakudo Perl6はPerl6のサブセットであるNQPを用いて記述されている. +%従ってyaccやlexと言ったPerl5の文字解析, 構文解析に利用していたプログラムは利用せず, NQP側で構文定義などを行っている. +%NQPはNQP自身でBootstrappingされている為, Rakudo Perl6のbuild時にはNQPの実行環境として要したVM, それに基づいてbuildしたNQPがそれぞれ必要となる. +% +% +% +%\subsection{現在のPerl6} +%Perl6の言語仕様\cite{perl6design}とその時点での実装状況をまとめた公式ドキュメント\cite{perl6doc}は分離している. +%従来は言語仕様は自然言語の仕様書であったが, 現在はテストスイートであるRoast\cite{roast}そのものと定義されている. +%現在のPerl6の仕様を読む場合Roastを確認し, 現在Rakudo上に実装されている機能を見る場合は公式ドキュメントを確認する必要がある. +% \subsection{処理速度} 現在のPerl6が他のプログラミング言語と比較した場合どのような違いがでるのか計測した. macOSの/var/log/system.logファイルから正規表現でログ中のプログラムが書き込んだ回数を個別に数え上げるというものである. @@ -268,7 +299,7 @@ \item Perl5 \end{itemize} -測定した結果を以下に示す.測定結果の単位は秒である. +測定した結果を表\ref{tbl001}に示す. 測定結果の単位は秒である. \begin{table}[htb] \begin{tabular}{|l|c|c|c|c|c|} \hline @@ -276,6 +307,7 @@ 231K & 0.86 & 21.48 & 0.27 & 0.04 \\ 3G & 2331.08 & 1665.56 & 48.85 & 41.35\\ \hline \end{tabular} +\caption{ログファイル処理時間の計測結果}\label{tbl001} \end{table} 計測結果からファイルサイズが小さい場合はMoarVMよりJVMに乗せたPerl6が低速であるが, ファイルサイズが大きい場合はJavaのJITが働くためMoarVMより高速に動いていると推測できる. @@ -316,45 +348,42 @@ この章では改良を行ったPerl6処理系であるMoarVMについて述べる. 今回改良を行ったMoarVMは2018.04.01であり, 利用したNQPは2018.04-3-g45ab6e3バージョンである. \subsection{方針} -Rakudo処理系の処理速度はNQPコンパイラ側の処理速度, 実行環境であるMoarVMなどのVM環境の主に2種類が影響していると考えられる. -NQP側はNQPで書かれている為, NQPの記述を修正すれば高速化することも考えられるが, 今回はVM側の処理系に着目した. -Rakudoが動作するVMは複数存在するが, MoarVMが現在主流の処理系である. -MoarVM自身はCで記述されているため, CbCを導入する事が可能である. -CbCの持つCodeGearや軽量継続を導入する事で, 通常のMoarVMと比較してよりきめ細やかな実装が出来ると推測される. -CodeGearをThreadedCodeなどに応用する事で, MoarVMの高速化が見込める. -また, CbCに関する今までの研究においては, CbCを言語処理系に応用した例が少ない為, CbCを言語処理系に適応した場合の挙動などを確認したい. -その為, 本稿ではCbCをMoarVMに導入したCbCMoarVMを実装する. +%Rakudo処理系の処理速度はNQPコンパイラ側の処理速度, 実行環境であるMoarVMなどのVM環境の主に2種類が影響していると考えられる. +%NQP側はNQPで書かれている為, NQPの記述を修正すれば高速化することも考えられるが, 今回はVM側の処理系に着目した. +%Rakudoが動作するVMは複数存在するが, MoarVMが現在主流の処理系である. +%MoarVM自身はCで記述されているため, CbCを導入する事が可能である. +%CbCの持つCodeGearや軽量継続を導入する事で, 通常のMoarVMと比較してよりきめ細やかな実装が出来ると推測される. +%CodeGearをThreadedCodeなどに応用する事で, MoarVMの高速化が見込める. +%また, CbCに関する今までの研究においては, CbCを言語処理系に応用した例が少ない為, CbCを言語処理系に適応した場合の挙動などを確認したい. +%その為, 本稿ではCbCをMoarVMに導入したCbCMoarVMを実装する. +% - -MoarVMそのものをCbCで書き換えることも考えられるがMoarVM自体既に巨大なプロジェクトである為すべてを書き換える事は困難である. -その為まず比較的CbCで書き換えることが容易な箇所を修正する. -前章までに述べた通りCbCのCodeGearはコンパイラの基本ブロックに該当する. +MoarVMの中心は, バイトコードを解釈する, バイトコードインタプリタ部分である. +その為CbCを用いて, MoarVMのバイトコードインタプリタ部分を記述し直し, CbCMoarVMとして実装する. +CbCのCodeGearはコンパイラの基本ブロックに該当する. 従ってMoarVMにおける基本ブロックの箇所をCodeGearに書き換える事が可能である. \subsection{MoarVMのバイトコードのディスパッチ} -MoarVMのバイトコードインタプリタはsrc/core/interp.cで定義されている. -この中の関数MVM\_interp\_runで命令に応じた処理を実行する. -関数内では命令列が保存されているcur\_op, 現在と次の命令を指し示すop, Threadの環境が保存されているThreadcontextなどの変数を利用する. -命令実行は大きく二種類の動作があり, Cのgotoが利用できる場合はCode\ref{orig_macro}に示すMVM\_CGOTOフラグが立ちラベル遷移を利用する. -それ以外の場合は巨大なcase文として命令を実行する. - -ラベル遷移を利用する場合はCode\ref{oplabelsh}に示すラベルテーブルLABELSにアクセスし, テーブルに登録されているアドレスを取得し, マクロNEXTで遷移する. -Code\ref{dispatch_c}に示すno\_opは何もせず次の命令に移動する為, goto NEXT;のみ記述されている. +%MoarVMのバイトコードインタプリタはsrc/core/interp.cで定義されている. +%この中の関数MVM\_interp\_runで命令に応じた処理を実行する. +%関数内では命令列が保存されているcur\_op, 現在と次の命令を指し示すop, Threadの環境が保存されているThreadcontextなどの変数を利用する. +%命令実行は大きく二種類の動作があり, Cのgotoが利用できる場合はCode\ref{orig_macro}に示すMVM\_CGOTOフラグが立ちラベル遷移を利用する. +%それ以外の場合は巨大なcase文として命令を実行する. +% +%ラベル遷移を利用する場合はCode\ref{oplabelsh}に示すラベルテーブルLABELSにアクセスし, テーブルに登録されているアドレスを取得し, マクロNEXTで遷移する. +%Code\ref{dispatch_c}に示すno\_opは何もせず次の命令に移動する為, goto NEXT;のみ記述されている. %このラベルテーブルの中身はラベルが変換されたアドレスであるため, 実際に呼ばれている命令コードの名前はデバッガレベルでは確認できない. %巨大なcase文として実行された場合, 実行時間が遅いだけでなく, ラベル遷移と共存させて記述を行っている為Cのソースコードにおける可読性も低下する. -\lstinputlisting[label=orig_macro, caption=interp.cのマクロ部分]{./src/orig_macro.c} -\lstinputlisting[label=oplabelsh, caption=ラベルテーブルの一部分]{./src/oplabels.h} - -\lstinputlisting[label=dispatch_c, caption=オリジナル版MoarVMのバイトコードディスパッチ]{./src/dispatch.c} +%\lstinputlisting[label=orig_macro, caption=interp.cのマクロ部分]{./src/orig_macro.c} +%\lstinputlisting[label=oplabelsh, caption=ラベルテーブルの一部分]{./src/oplabels.h} +% +%\lstinputlisting[label=dispatch_c, caption=オリジナル版MoarVMのバイトコードディスパッチ]{./src/dispatch.c} interp.cでは命令コードのディスパッチはマクロを利用したcur\_opの計算及びラベルの遷移, もしくはマクロDISPATCHが展開するswitch文で行われていた. -この為MoarVM内の命令コードに対応する処理は, 命令ディスパッチが書かれているCソースファイルの, 特定の場所のみに記述せざるを得ない. -その為命令コードのモジュール化などが行えず, 1ファイル辺りの記述量が膨大になってしまう. -また各命令コードに対応する処理は, ラベルジャンプもしくはswitch文に展開されてしまう為, Threaded Codeの実装を考えた場合, 大幅なコードの改修が要求される. -デバッグ時には, Cレベルでのデバッグ時にはアドレスと実際に呼ばれる箇所を確認する事に手間がかかる. +このディスパッチ方法では, ラベルジャンプや巨大なcase文として記述する必要があり, ファイルが冗長になるなどの問題が生じる. CbCMoarVMではこの問題を解決するために, それぞれの命令に対応するCodeGearを作成し, 各CodeGearの名前を要素として持つCbCのCodeGearのテーブルを作成した. このCodeGearのテーブルを参照するCodeGearはcbc\_nextであり, この中のマクロNEXTはinterp.cのマクロNEXTをCbC用に書き直したものである. @@ -481,16 +510,16 @@ その為, 正常に動作しているMoarVMのバイナリmoarとnqpを用意し, このnqp側からMoarVMのバイトコードにNQPで記述されたテストを変換する. 変換されたMoarVMのバイトコードはバイナリmoarに渡す事で実行可能であり, テストを行う事が出来る. -\subsection{CbCコンパイラによるバグ} -これまでのCbCに関する研究においては, 複数個の入出力をCodeGearに与えるユースケースで利用していた. -CbCコンパイラ自身はそれぞれ用意したテストスイートを通化するものの, MoarVMの様な巨大なプロジェクトのCodeGearをコンパイルを実行する場合, 予期せぬバグが発生した. -主にCodeGear間のgotoにおけるtail callフラグの除去や, DataGearとして渡している構造体の変数のアドレスがスタックポインタの値より上位に来てしまい, 通常のCの関数をcallした際にローカル変数の領域がDataGearのアドレスの周辺を利用してしまう. -その為DataGearの構造体の値が書き換わり, CからDataGearにreturnした際にDataGearの構造体が破壊されるバグである. -このバグは先程の並列デバッグを行いながらプログラムカウンタや変数の動きをトレースする事などで発見することが出来る. -現状ではCbCコンパイラがプログラマの意図と反する挙動を取るためCbCコンパイラのバグを回避するプログラミングが要求されている. -本来コンパイラ側のバグを回避するプログラミングをプログラマに要求する事は好ましくない. -従ってCbCコンパイラ自身の信頼性を向上させる事も今後の課題となっている. - +%\subsection{CbCコンパイラによるバグ} +%これまでのCbCに関する研究においては, 複数個の入出力をCodeGearに与えるユースケースで利用していた. +%CbCコンパイラ自身はそれぞれ用意したテストスイートを通化するものの, MoarVMの様な巨大なプロジェクトのCodeGearをコンパイルを実行する場合, 予期せぬバグが発生した. +%主にCodeGear間のgotoにおけるtail callフラグの除去や, DataGearとして渡している構造体の変数のアドレスがスタックポインタの値より上位に来てしまい, 通常のCの関数をcallした際にローカル変数の領域がDataGearのアドレスの周辺を利用してしまう. +%その為DataGearの構造体の値が書き換わり, CからDataGearにreturnした際にDataGearの構造体が破壊されるバグである. +%このバグは先程の並列デバッグを行いながらプログラムカウンタや変数の動きをトレースする事などで発見することが出来る. +%現状ではCbCコンパイラがプログラマの意図と反する挙動を取るためCbCコンパイラのバグを回避するプログラミングが要求されている. +%本来コンパイラ側のバグを回避するプログラミングをプログラマに要求する事は好ましくない. +%従ってCbCコンパイラ自身の信頼性を向上させる事も今後の課題となっている. +% \section{CbCMoarVMの利点と欠点} @@ -548,13 +577,13 @@ % \end{table} しかし, 言語処理系は広く使われる為に著名なOSSなどを利用して開発するのが望ましいが, CbCプロジェクトの認知度が低いという現状がある. -また, 前章までに複数述べた通りCbCコンパイラが現在非常にバグを発生させやすい状態になっている. +また, CbCコンパイラが現在非常にバグを発生させやすい状態になっている. CbCコンパイラはgccとllvm/clang上に実装している為, これらのアップデートに追従する必要がある. しかしコンパイラのバージョンに応じてCbCで利用するコンパイラ内のAPIが異なる場合が多く, APIの変更に伴う修正作業などを行う必要がある. CbCMoarVMではCからCodeGearへ, CodeGearからCへの遷移などが複数回繰り返されているが, この処理中のCodeGearでのtail callの強制が非常に難関である. tail callの強制には関数定義の箇所や引数, スタック領域のサイズ修正などを行う必要がある. -現在のバグではCodeGear内部での不要なスタック操作命令を完全に排除しきれていない. +現在のCbCコンパイラのバグではCodeGear内部での不要なスタック操作命令を完全に排除しきれていない. またCodeGearからCに帰る場合, 環境付き継続を行う必要がある. Cの関数の末尾でCodeGearを呼び出している場合など環境付き継続を使用しなくても良いケースは存在するが, 頻繁にCとCbCを行き来する場合記述が冗長になる可能性はある. @@ -611,7 +640,7 @@ CbCMoarVMではオリジナルのMoarVMと比較して以下の様な利点が見られた. \begin{itemize} - \item CodeGear単位で命令処理を記述する事が可能となり, モジュール化が可能となった. + \item CodeGear単位で命令処理を記述する事が可能となり, モジュール化が可能となった. \item ThreadedCodeを実装する際に効率的に実装ができる見込みが立った. \item CodeGearを導入した命令単位での最適化が可能となった. \item break pointを命令の処理単位でかける事が可能となった. @@ -621,7 +650,7 @@ 今後CbCでの開発をより深く行っていくにあたり, CbCコンパイラそのものの信頼性を向上させる必要がある. MoarVMの開発を行うにあたり新たに発見された複数のバグを修正し, より安定するコンパイラにする為に改良を行う. -現在CbCMoarVMで直接バイトコードを入力した場合のNQPのテストはJVM, JavaScriptのテストを除く中で80\%パスする. +現在CbCMoarVMで直接バイトコードを入力した場合のNQPのテストはJVMなどのテストを除く中で80\%パスする. また数値の計算と出力などの簡単なNQPの例題を作成し, オリジナルのNQP,MoarVMでバイトコード化したものを入力した際も正常に動作している. しかしNQPのセルフビルドは現在オブジェクトの生成に一部失敗している為成功していない. 今後はさらに複雑な例題やNQPのセルフビルド, Perl6の動作を行っていく. diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/fig/perl6nqp.pdf Binary file Paper/fig/perl6nqp.pdf has changed diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/fig/tgraph.pdf Binary file Paper/fig/tgraph.pdf has changed diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/reference.bib --- a/Paper/reference.bib Fri Nov 30 11:44:49 2018 +0900 +++ b/Paper/reference.bib Fri Nov 30 19:22:26 2018 +0900 @@ -142,18 +142,44 @@ month = 2, } -@misc{threadecodes, - title = {Threaded Code}, - author = {Bell, James R}, - journal = {Communications of the ACM 16.6}, - year = 1973, +@article{Bell:1973:TC:362248.362270, + author = {Bell, James R.}, + title = {Threaded Code}, + journal = {Commun. ACM}, + issue_date = {June 1973}, + volume = {16}, + number = {6}, + month = jun, + year = {1973}, + issn = {0001-0782}, + pages = {370--372}, + numpages = {3}, + url = {http://doi.acm.org/10.1145/362248.362270}, + doi = {10.1145/362248.362270}, + acmid = {362270}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {compiled code, interpreter, machine code, space tradeoff, subroutine calls, threaded code, time tradeoff}, } -@journal{optthreade, - title = {Optimizing direct threaded code by selective inlining}, - author = {Piumarta, Ian and Fabio Riccardi}, - journal = {ACM SIGPLAN Notices. Vol. 33}, - year = 1998, + + +@inproceedings{Piumarta:1998:ODT:277650.277743, + author = {Piumarta, Ian and Riccardi, Fabio}, + title = {Optimizing Direct Threaded Code by Selective Inlining}, + booktitle = {Proceedings of the ACM SIGPLAN 1998 Conference on Programming Language Design and Implementation}, + series = {PLDI '98}, + year = {1998}, + isbn = {0-89791-987-4}, + location = {Montreal, Quebec, Canada}, + pages = {291--300}, + numpages = {10}, + url = {http://doi.acm.org/10.1145/277650.277743}, + doi = {10.1145/277650.277743}, + acmid = {277743}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {bytecode interpretation, dynamic translation, inlining, just-in-time compilation, threaded code}, } @webpage{luajit, diff -r dec42afa6aaa -r 1b1089b0aef5 Paper/src/perl6nqp.graffle Binary file Paper/src/perl6nqp.graffle has changed