Mercurial > hg > Papers > 2019 > anatofuz-prosym
comparison Paper/anatofuz.tex @ 25:7a2d604607d8
add debugging MoarVM
author | Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 09 Nov 2018 00:31:25 +0900 |
parents | d8f77d0a3452 |
children | df723be56106 |
comparison
equal
deleted
inserted
replaced
24:d8f77d0a3452 | 25:7a2d604607d8 |
---|---|
285 moarに対してmoarvm bytecodeをdumpオプションを付けて読み込ませるとmoarvmのbytecodeがアセンブラの様に出力される. | 285 moarに対してmoarvm bytecodeをdumpオプションを付けて読み込ませるとmoarvmのbytecodeがアセンブラの様に出力される. |
286 しかしこれはmoarvmが実行したbytecodeのトレースではなくmoarvm bytecodeを変換したものに過ぎない. | 286 しかしこれはmoarvmが実行したbytecodeのトレースではなくmoarvm bytecodeを変換したものに過ぎない. |
287 また,明らかに異なる挙動を示す両者のmoarを利用しても同じ結果が返ってきてしまう. | 287 また,明らかに異なる挙動を示す両者のmoarを利用しても同じ結果が返ってきてしまう. |
288 そのため今回のMoarVMBytecodeインタプリタの実装のデバッグにはこの方法は適さない. | 288 そのため今回のMoarVMBytecodeインタプリタの実装のデバッグにはこの方法は適さない. |
289 従って実際に実行した命令を確認するにはgdbなどのCデバッガを利用してMoarVMを直接トレースする必要がある. | 289 従って実際に実行した命令を確認するにはgdbなどのCデバッガを利用してMoarVMを直接トレースする必要がある. |
290 \lstinputlisting[label=debug_origmoar, caption=オリジナル版MoarVMのバイトコードのトレース]{./src/origin_breakpoint.txt} | 290 |
291 CbC側はcbc\_nextにbreak pointを設定し,オリジナル側は次のオペコードの設定のマクロにダミーの関数を呼び出すように修正し,そこにbreak pointを設定する. | |
292 CbC側ではCodeSegmentの名前をデバッガ上で直接確認できるが,オリジナル版はLABLEの配列の添え字から自分でどのオペコードに対応しているかをデバッガの外で探す必要がある. | |
293 | |
294 添字を確認するためにはCode\ref{orig_b}に示すようにオリジナルのMoarVMの場合cur\_opの値をMVMuint16のポインタでキャストし,これが指す値を出力する. | |
295 break pointを掛けているダミー関数ではcur\_opにアクセスする事が出来ない為,スタックフレームを一つupする必要がある. | |
296 \lstinputlisting[label=orig_b, caption=オリジナル版MoarVMに対してのbreak point設定]{./src/origin_b_set.txt} | |
291 | 297 |
292 | 298 |
293 \subsection{MoarVMの並列デバッグ手法} | 299 \subsection{MoarVMの並列デバッグ手法} |
294 しかしMoarVMが実行する命令は膨大な数がある. | 300 しかしMoarVMが実行する命令は膨大な数がある. |
295 その為gdbでMoarVMをCbCとオリジナル版での並列デバッグを人間が同時に行うことは困難である. | 301 その為gdbでMoarVMをCbCとオリジナル版での並列デバッグを人間が同時に行うことは困難である. |
296 Perlなどのスクリプトを用いて自動的に解析したいため,ログを残す為にscriptコマンドを実行した状態でgdbを起動する. | 302 Perlなどのスクリプトを用いて自動的に解析したいため,ログを残す為にscriptコマンドを実行した状態でgdbを起動する. |
297 CbC側はcbc\_nextにbreak pointを設定し,オリジナル側は次のオペコードの設定のマクロにダミーの関数を呼び出すように修正し,そこにbreak pointを設定する. | 303 |
298 CbC側ではCodeSegmentの名前を直接確認できるが,オリジナル版はLABLEの配列の添え字から自分でどのオペコードに対応しているかを探す必要がある. | 304 |
305 \lstinputlisting[label=debug_origmoar, caption=オリジナル版MoarVMのバイトコードのトレース]{./src/origin_breakpoint.txt} | |
306 | |
299 CbCとオリジナルのCODES,LABELの添字は対応している為,ログの解析を行う際はそれぞれの添字を抽出し違いが発生している箇所を探索する. | 307 CbCとオリジナルのCODES,LABELの添字は対応している為,ログの解析を行う際はそれぞれの添字を抽出し違いが発生している箇所を探索する. |
308 これらはscriptコマンドが作成したログを元に異なる箇所を発見するスクリプトを用意し自動化する. | |
309 \lstinputlisting[label=logs2, caption=バイトコードの差分検知の一部分]{./src/logs2.txt} | |
310 | |
300 違いが生じている箇所が発見できた場合,その前後のCodeSegment及びディスパッチ部分にbreak pointをかけ,それぞれの変数の挙動を比較する. | 311 違いが生じている箇所が発見できた場合,その前後のCodeSegment及びディスパッチ部分にbreak pointをかけ,それぞれの変数の挙動を比較する. |
301 主にcbc\_return系の命令が実行されている場合は,その直前で命令を切り替えるcbc\_invoke系統の命令が呼ばれているが,この周辺で何かしらの違いが発生している可能性が高い. | 312 主にcbc\_return系の命令が実行されている場合は,その直前で命令を切り替えるcbc\_invoke系統の命令が呼ばれているが,この周辺で何かしらの違いが発生している可能性が高い. |
302 またCbCコンパイラのバグが生じている可能性もある為,アセンブラレベルの命令を確認しながらデバッグを進めることとなる. | 313 また主に次のCodeSegmentに遷移する際にCbCコンパイラのバグが生じている可能性もある為,アセンブラレベルの命令を確認しながらデバッグを進めることとなる. |
303 | 314 |
304 | 315 |
305 | 316 |
306 \subsection{CbCコンパイラによるバグ} | 317 \subsection{CbCコンパイラによるバグ} |
307 現在までのCbCは複数個の入出力をCodeSegmentに与えるユースケースで利用していた. | 318 現在までのCbCは複数個の入出力をCodeSegmentに与えるユースケースで利用していた. |
308 CbCコンパイラ自身はそれぞれ用意したテストスイートを通化するものの,MoarVMの様な巨大なプロジェクトのCSをコンパイルを実行する場合,予期せぬバグが発生した. | 319 CbCコンパイラ自身はそれぞれ用意したテストスイートを通化するものの,MoarVMの様な巨大なプロジェクトのCSをコンパイルを実行する場合,予期せぬバグが発生した. |
309 主にCS間のgotoにおけるtail callフラグの除去や,DSとして渡している構造体の変数のアドレスがスタックポインタの値より上位に来てしまい,通常のCの関数をcallした際にローカル変数の領域がDSのアドレスの周辺を利用してしまう. | 320 主にCS間のgotoにおけるtail callフラグの除去や,DSとして渡している構造体の変数のアドレスがスタックポインタの値より上位に来てしまい,通常のCの関数をcallした際にローカル変数の領域がDSのアドレスの周辺を利用してしまう. |
310 その為DSの構造体の値が書き換わり,CからDSにreturnした際にDSの構造体が破壊されるバグである. | 321 その為DSの構造体の値が書き換わり,CからDSにreturnした際にDSの構造体が破壊されるバグである. |
311 このバグは先程の並列デバッグを行いながらプログラムカウンタや変数の動きをトレースする事などで発見することが出来る. | 322 このバグは先程の並列デバッグを行いながらプログラムカウンタや変数の動きをトレースする事などで発見することが出来る. |
312 現状ではCbCコンパイラがプログラマの意図と反する挙動を取るためCbCコンパイラのバグを回避するプログラミングが要求されている. | 323 現状ではCbCコンパイラがプログラマの意図と反する挙動を取るためCbCコンパイラのバグを回避するプログラミングが要求されている. |
313 本来コンパイラ側のバグを回避するプログラミングをプログラマに要求するスタイルは好ましくない. | 324 本来コンパイラ側のバグを回避するプログラミングをプログラマに要求する事は好ましくない. |
314 従ってCbCコンパイラ自身の信頼性を向上させる事も今後の課題となっている. | 325 従ってCbCコンパイラ自身の信頼性を向上させる事も今後の課題となっている. |
315 | 326 |
327 また現在はclang上に実装したCbCコンパイラではtaill call除去のエラーが発生してしまう為コンパイルする事が出来ない. | |
328 その為現在はgcc上に実装したcbcコンパイラを利用しgdbを利用しデバッグを行う. | |
316 \subsection{Threaded Code} | 329 \subsection{Threaded Code} |
317 CbCはCodeSegmentで末尾最適化(Tail call optimization)を行う. | 330 CbCはCodeSegmentで末尾最適化(Tail call optimization)を行う. |
318 これはCodeSegmentは必ず関数呼び出しではなくgotoで次の状態に遷移する為にスタック領域の操作が必要とならない為である. | 331 これはCodeSegmentは必ず関数呼び出しではなくgotoで次の状態に遷移する為にスタック領域の操作が必要とならない為である. |
319 現在のCbCコンパイラの実装ではCodeSegmentからCの関数に戻る場合は末尾最適化を切り,CodeSegment間の遷移では末尾最適化が行われる. | 332 現在のCbCコンパイラの実装ではCodeSegmentからCの関数に戻る場合は末尾最適化を切り,CodeSegment間の遷移では末尾最適化が行われる. |
320 末尾最適化を応用することでContinuation-passingスタイルのThreaded Codeの実装が可能となる.\cite{threadedcode} | 333 末尾最適化を応用することでContinuation-passingスタイルのThreaded Codeの実装が可能となる.\cite{threadedcode} |
328 \subsubsection{perlcc} | 341 \subsubsection{perlcc} |
329 Perl5においてはperlccというモジュールが開発されている. | 342 Perl5においてはperlccというモジュールが開発されている. |
330 これはPerl5内部で利用しているPerlバイトコードを,PerlのC APIであるXS言語の様なCのソースファイルに埋め込み,それをCコンパイルでコンパイルするというものである. | 343 これはPerl5内部で利用しているPerlバイトコードを,PerlのC APIであるXS言語の様なCのソースファイルに埋め込み,それをCコンパイルでコンパイルするというものである. |
331 perlccを利用することでPerlインタプリタが無い状況でも可動するバイナリファイルを作成する事が可能である. | 344 perlccを利用することでPerlインタプリタが無い状況でも可動するバイナリファイルを作成する事が可能である. |
332 しかしPerlccはPerlスクリプトが複雑になるほど正確にCに移植を行う事が出来ず,現在ではPerlのコアモジュールから外されている. | 345 しかしPerlccはPerlスクリプトが複雑になるほど正確にCに移植を行う事が出来ず,現在ではPerlのコアモジュールから外されている. |
333 PerlccはPerlのバイトコードをCに変換しただけであり,Cで実装されているPerl経由で実行した場合と処理速度はほぼ変わらない. | 346 PerlccはPerlのバイトコードをCへの変換のみ行う為,Cで実装されているPerl経由で実行した場合と処理速度はほぼ変わらない. |
334 またPerlccで生成されたCのソースコードは難解であり,これをデバッグするのが困難でもある. | 347 またPerlccで生成されたCのソースコードは難解であり,これをデバッグするのが困難でもある. |
335 MoarVMでthreaded codeを実現出来た場合,その箇所のみCbCプログラムとして切り出す事が可能である為perlccと似たツールを作成することも可能である. | 348 MoarVMでthreaded codeを実現出来た場合,その箇所のみCbCプログラムとして切り出す事が可能である為perlccと似たツールを作成することも可能である. |
336 この場合,Perl6を通常動かした際とは異なりバイトコードインタプリタに到達する前の処理が無くなる為多少の高速化が望めると推測できる. | 349 この場合,Perl6を通常動かした際とは異なりバイトコードインタプリタに到達する前の処理が無くなる為多少の高速化が望めると推測できる. |
337 | 350 |
338 \section{CbCを用いる事についての利点と欠点} | 351 \section{CbCを用いる事についての利点と欠点} |
347 関数単位での処理の比重が偏る事に加え, | 360 関数単位での処理の比重が偏る事に加え, |
348 switch文中に書かれている処理は他の関数から呼ぶ事が出来ないため,余計な手間がかかる箇所が発生すると考えられる. | 361 switch文中に書かれている処理は他の関数から呼ぶ事が出来ないため,余計な手間がかかる箇所が発生すると考えられる. |
349 | 362 |
350 CbCMoarVMの場合,CodeSegmentとして基本ブロックを記述出来る為オリジナルのMoarVMの様にswtich文のブロック中に書く必要性が無くなる. | 363 CbCMoarVMの場合,CodeSegmentとして基本ブロックを記述出来る為オリジナルのMoarVMの様にswtich文のブロック中に書く必要性が無くなる. |
351 その為類似する命令系をコード分割し,モジュール化する事が可能である. | 364 その為類似する命令系をコード分割し,モジュール化する事が可能である. |
352 これは通常のインタプリタの実装と比べ可読性と言う意味とモノリシックアーキテクチャをマイクロ化出来るという意味でも利点である. | 365 これは通常のインタプリタの実装と比べ可読性と言う意味とCodeSegmentを再利用ができ,さらに分割可能という意味でも利点である. |
353 | 366 |
354 \subsubsection{MoarVMのデバッグ} | 367 \subsubsection{MoarVMのデバッグ} |
355 MoarVMのバイトコードインタプリタの箇所はオリジナルの実装ではラベルジャンプを用いて実装されている. | 368 MoarVMのバイトコードインタプリタの箇所はオリジナルの実装ではラベルジャンプを用いて実装されている. |
356 その為,直接ラベルにbreak pointをかける事が出来ない. | 369 その為,直接ラベルにbreak pointをかける事が出来ない. |
357 作業者がデバッガが読み込んでいるCソースコードの位置を把握し,行番号を指定してdebug pointを設定する必要があった. | 370 作業者がデバッガが読み込んでいるCソースコードの位置を把握し,行番号を指定してdebug pointを設定する必要があった. |