diff Slide/slide.md @ 90:1f9baa69dfe0

update
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 11 Jan 2019 00:01:18 +0900
parents 632f160ccbd0
children 3beea12854b0
line wrap: on
line diff
--- a/Slide/slide.md	Thu Jan 10 21:57:54 2019 +0900
+++ b/Slide/slide.md	Fri Jan 11 00:01:18 2019 +0900
@@ -6,27 +6,29 @@
 
 
 ## 研究目的
--  スクリプト言語であるPerl5の後継言語としてPerl6が現在開発されている.
--  現在主流なPerl6の実装にRakudoがあり, RakudoはNQP(Perl6のサブセット)で記述されたPerl6, NQPで記述されたNQPコンパイラがある
--  NQPコンパイラはRakudoのVMであるMoarVM用のバイトコードを生成し, MoarVMはこのバイトコードを解釈, 実行する
--  Continuation based C (CbC)という言語は継続を基本とするC言語であり, 言語処理系に応用出来ると考えられる
--  CbC一部用いてMoarVMの書き換えを行い, 処理を検討する.
+- 現在開発されているPerl6の実装にRakudoがあり, RakudoはNQP(Perl6のサブセット)で記述されたPerl6, NQPで記述されたNQPコンパイラ, NQPを解釈するVMで構成されている
+- NQPコンパイラはRakudoのVMであるMoarVM用のバイトコードを生成し, MoarVMはこのバイトコードを解釈, 実行する
+- Continuation based C (CbC)という言語は継続を基本とするC言語であり, 言語処理系に応用出来ると考えられる
+- スクリプ言語などは, バイトコードを扱うが, この実行にcae文や, ラベルgotoなどを利用しており, この部分はCbCの機能で書き換える事が可能である
+- 従って, CbC一部用いてPerl6にC処理系であるMoarVMの書き換えを行い, 処理を検討する.
+![](fig/perl6nqp.svg)
+- (Rakudoの構成図)
 
 ## Continuation Based C (CbC)
-
 - Continuation Based C (CbC) はCodeGearを単位として用いたプログラミング言語である.
 - CodeGearはCの通常の関数呼び出しとは異なり,スタックに値を積まず, 次のCodeGearにgoto文によって遷移する.
-- このgoto文による遷移を軽量継続と呼ぶ.
 - CodeGearはCの関数宣言の型名の代わりに`__code`と書く事で宣言出来る.
+- CodeGearの引数は, 各CodeGearの入出力として利用する.
 
 ```
 extern int printf(const char*,...);
-  int main (){
-     int data = 0;
-     goto cg1(&data);
+
+int main (){
+    int data = 0;
+    goto cg1(&data);
 }
 __code cg1(int *datap){
-      (*datap)++;
+    (*datap)++;
     goto cg2(datap);
 }
 __code cg2(int *datap){
@@ -54,13 +56,12 @@
 - 実行環境のVM, Perl6のサブセットであるNQP(NotQuitPerl), NQPで記述されたPerl6(Rakudo)という構成になっている.
 - コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である
 
-- 現在はMoarVMがRakudoの中でも主流なVM実装となっている.
 
 ## MoarVM
 
 - Perl6専用のVMであり, Cで記述されている
 - レジスタマシンとして実装されている.
-- MoarVMはバイトコードインタプリタを `src/core/interp.c` で定義しており, この中の関数 `MVM_interp_run` で命令に応じた処理を実行する
+- MoarVMはバイトコードインタプリタを `src/core/interp.c` で定義しており, この中の関数 `MVM_interp_run` でバイトコードに応じた処理を実行する
 
 ## MVM_interp_run
 
@@ -137,16 +138,11 @@
 - このテーブルは`cbc_next`というCodeGearから参照し, 以降はこのCodeGearの遷移として処理が継続される.
 
 ```
-#define NEXT_OP(i) (i->op = *(MVMuint16 *)(i
-    ->cur_op), i->cur_op += 2, i->op)
+#define NEXT_OP(i) (i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)
 #define DISPATCH(op) {goto (CODES[op])(i);}
 #define OP(name) OP_ ## name
 #define NEXT(i) CODES[NEXT_OP(i)](i)
 static int tracing_enabled = 0;
-
-_code cbc_next(INTERP i){
-    goto NEXT(i);
-}
 ```
 
 ```
@@ -193,44 +189,24 @@
 - `OP(.*)`の`(.*)`の部分をCodeGearの名前として先頭に `cbc_` をつけた上で設定する.
 - cur_opなどはINTERPを経由してアクセスする様に修正する.
 - 末尾の `NEXT` を次のCodeGearにアクセスする為に `cbc_next` に修正する.
-- case文で次のcase文に流れる箇所は, 直接その下のcase文に該当するCodeGearに遷移する.
-- GC対策の為に, CodeGear中のローカル変数をグローバル変数の配列に保存している箇所は,CodeGearに直接処理を書かず, CodeGearから別の関数を呼び出す形に修正する
-    - その際に, 保存するローカル変数をstatic変数に修正するなどの工夫を行う
 
 
 ```
-__code cbc_no_op(INTERP i){
-    goto cbc_next(i);
-}
-__code cbc_const_i8(INTERP i){
-    goto cbc_const_i16(i);
+
+__code cbc_next(INTERP i){
+    __code (*c)(INTERP)
+    c = CODES[(i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)]; // c = NEXT(i)
+    goto c(i);
 }
-__code cbc_const_i16(INTERP i){
-    goto cbc_const_i32(i);
+_code cbc_next(INTERP i){
+    goto 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);
 }
-__code cbc_pushcompsc(INTERP i){
-    MVMObject * sc;
-    sc  = GET_REG(i->cur_op, 0,i).o;
-    if (REPR(sc)->ID != MVM_REPR_ID_SCRef)
-        MVM_exception_throw_adhoc(i->tc, "Can only push an SCRef with pushcompsc");
-    if (MVM_is_null(i->tc, i->tc->compiling_scs)) {
-        MVMROOT(i->tc, sc, {
-            i->tc->compiling_scs = MVM_repr_alloc_init(i->tc, i->tc->instance->boot_types.BOOTArray);
-        });
-    }
-    MVM_repr_unshift_o(i->tc, i->tc->compiling_scs, sc);
-    i->cur_op += 2;
-    goto cbc_next(i);
-}
 ```
 
 ## NQP
@@ -253,6 +229,36 @@
 say(add_test(10));
 ```
 
+## NQPのバイトコード
+
+- NQPはMoarVMのバイトコードにコンパイルし, バイトコードをファイルに保存することが可能である
+- MoarVMのバイトコードは, アセンブリの様にダンプする事が可能である
+- 実際に先程のコードをバイトコードにコンパイルし, 対応するバイトコードをダンプすると次の様に表示される
+
+
+```
+     annotation: hoge.nqp:3
+     label_1:
+00007      const_i64_16       loc_2_int, 1
+00008      gt_i               loc_2_int, loc_0_int, loc_2_int
+00009      unless_i           loc_2_int, label_2(00022)
+00010      osrpoint
+     annotation: hoge.nqp:4
+00011      decont             loc_3_obj, loc_1_obj
+00012      smrt_numify        loc_4_num, loc_3_obj
+00013      coerce_ni          loc_5_int, loc_4_num
+00014      add_i              loc_5_int, loc_5_int, loc_0_int
+00015      hllboxtype_i       loc_3_obj
+00016      box_i              loc_3_obj, loc_5_int, loc_3_obj
+00017      set                loc_1_obj, loc_3_obj
+     annotation: hoge.nqp:5
+00018      const_i64_16       loc_5_int, 1
+00019      sub_i              loc_5_int, loc_0_int, loc_5_int
+00020      set                loc_0_int, loc_5_int
+00021      goto               label_1(00007)
+```
+
+
 ## MoarVMのデバッグ手法
 
 - MoarVMはバイトコードをランダムに生成する仕様となっている
@@ -360,10 +366,19 @@
 53 : 53
 *54 : 8
 ```
+
 ## 現在のCbCMoarVM
 
 - 現在はNQP, Rakudoのセルフビルドが達成でき, オリジナルと同等のテスト達成率を持っている
 - moarの起動時のオプションとして `--cbc` を与えることによりCbCで動き, そうでない場合は通常のCで記述された箇所で実行される
+- Perl6の実行バイナリperl6, NQPの実行バイナリnqp は, それぞれmoarを起動するシェルスクリプトである為, `--cbc` オプションをシェルスクリプト内に書き加えることで, Perl6, NQPがそれぞれCbCで起動する
+
+```
+#!/bin/sh
+exec /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/bin/moar --cbc \
+     --libpath=/mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib \
+     /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib/nqp.moarvm "$@"
+```
 
 ## CbCMoarVMの利点