# HG changeset patch # User anatofuz # Date 1555667592 -32400 # Node ID 4b1eb4d6969547550cd7651a9c24f690198b1dba # Parent 642787982a808a77b05eacf00abdc82f8adae212 update diff -r 642787982a80 -r 4b1eb4d69695 slide.html --- a/slide.html Fri Apr 19 18:24:04 2019 +0900 +++ b/slide.html Fri Apr 19 18:53:12 2019 +0900 @@ -444,7 +444,7 @@

NQPスクリプト(nまでの整数の和)

sub add_test($n){
-    mu $sum := 0;
+    my $sum := 0;
     while ( $n > 1) {
         $sum := $sum + $n;
         --$n;
@@ -461,13 +461,25 @@
 
 
-

NQPとオペコード

+

NQP

  • NQPはPerl6の中で一番レイヤーが低い言語
  • その為、 実行するVMのオペコード(処理単位)を使用することができる
  • +
  • NQPオペコードは、 Perl6の内部の抽象構文木でも使用されている
  • +
  • また、 Perl6と同様に型を指定することが可能
+
sub add_test(int $n){
+    mu $sum := 0;
+    while nqp::isgt_i($n,1) {
+        $sum := nqp::add_i($sum,$n);
+        $n   := nqp::sub_i($n,1);
+    }
+    return $sum;
+}
+
+
@@ -528,9 +540,147 @@

バイトコード

  • Perl6も、Rakudo/NQPはバイトコードに変換され、 バイトコードをVMが実行する
  • -
  • バイトコード実行部分は、 命令に対応するバイト列を読み込み、 解釈し、 次の命令を読み取ることを繰り返す
  • +
  • Perl6/NQPはバイトコードにコンパイルすることが可能 +
      +
    • 直接実行することはできない
    • +
    +
  • +
+ +
$nqp --target=mbc --output=fib.moarvm fib.nqp
+
+ + + + + +
+ +

バイトコードとMoarVM

+ +
    +
  • MoarVMバイトコードはMoarVMの実行バイナリ moar でディスアセンブルすることが可能
+
     annotation: add_test.nqp:1
+00003      const_i64_16       loc_2_int, 0
+00004      hllboxtype_i       loc_3_obj
+00005      box_i              loc_3_obj, loc_2_int, loc_3_obj
+00006      set                loc_1_obj, loc_3_obj
+     label_1:
+00007      decont             loc_3_obj, loc_0_obj
+00008      smrt_numify        loc_4_num, loc_3_obj
+00009      const_i64_16       loc_2_int, 1
+00010      coerce_in          loc_5_num, loc_2_int
+00011      gt_n               loc_2_int, loc_4_num, loc_5_num
+00012      unless_i           loc_2_int, label_2(00031)
+00013      osrpoint
+     annotation: add_test.nqp:3
+00014      decont             loc_3_obj, loc_1_obj
+00015      smrt_numify        loc_5_num, loc_3_obj
+00016      decont             loc_3_obj, loc_0_obj
+00017      smrt_numify        loc_4_num, loc_3_obj
+00018      add_n              loc_4_num, loc_5_num, loc_4_num
+00019      hllboxtype_n       loc_3_obj
+00020      box_n              loc_3_obj, loc_4_num, loc_3_obj
+00021      set                loc_1_obj, loc_3_obj
+00022      decont             loc_3_obj, loc_0_obj
+00023      smrt_numify        loc_4_num, loc_3_obj
+00024      coerce_ni          loc_6_int, loc_4_num
+00025      const_i64_16       loc_7_int, 1
+00026      sub_i              loc_7_int, loc_6_int, loc_7_int
+00027      hllboxtype_i       loc_3_obj
+00028      box_i              loc_3_obj, loc_7_int, loc_3_obj
+00029      set                loc_0_obj, loc_3_obj
+00030      goto               label_1(00007)
+
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
say(add_test(10000));
+
+ +
     annotation: add_test.nqp:1
+     label_1:
+00020      getlex_no          loc_7_obj, '&say'
+00021      decont             loc_7_obj, loc_7_obj
+00022      const_s            loc_3_str, '&add_test'
+00023      getlexstatic_o     loc_8_obj, loc_3_str
+00024      decont             loc_8_obj, loc_8_obj
+00025      const_i64_16       loc_5_int, 10000
+00026      prepargs           Callsite_1
+00027      arg_i              0, loc_5_int
+00028      invoke_o           loc_8_obj, loc_8_obj
+00029      prepargs           Callsite_0
+00030      arg_o              0, loc_8_obj
+00031      invoke_v           loc_7_obj
+00032      null               loc_7_obj
+00033      return_o           loc_7_obj
+
+ +
    +
  • Perl6の変数は直接実態を参照せず、中身が入っているコンテナを参照するようになっている。
  • +
  • その為 decont 命令で、コンテナの中身をレジスタに設定する必要がある
  • +
  • const_i64_16 などは64bitの数という意味で、 int 型としてレジスタに登録している
  • +
  • prepargs で引数の確認を行い, invoke_o で実際にサブルーチンに移行する
  • +
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
my $sum := 0;
+
+ +
     annotation: add_test.nqp:1
+00003      const_i64_16       loc_2_int, 0
+00004      hllboxtype_i       loc_3_obj
+00005      box_i              loc_3_obj, loc_2_int, loc_3_obj
+00006      set                loc_1_obj, loc_3_obj
+
+ +
    +
  • まず loc_2 レジスタをint型の整数0で初期化する
  • +
  • 変数 $sum はint型の指定がないので、 obj型で登録しなければならない
  • +
  • その為, 整数として登録された loc_2 から、 obj型に一旦キャストし、 loc_3 レジスタに設定したものを、 loc_1 レジスタに設定する
  • +
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
    while ( $n > 1) {
+
+ +
     label_1:
+00007      decont             loc_3_obj, loc_0_obj
+00008      smrt_numify        loc_4_num, loc_3_obj
+00009      const_i64_16       loc_2_int, 1
+00010      coerce_in          loc_5_num, loc_2_int
+00011      gt_n               loc_2_int, loc_4_num, loc_5_num
+00012      unless_i           loc_2_int, label_2(00031)
+00013      osrpoint
+
+ +
    +
  • 変数 $n と 整数 1 を大小比較する為、 まず $n から値を取り出す
  • +
  • 比較にもint型の指定がない為、 num 型にキャストし、 num 型のレジスタでの大小を比較する
  • +
  • 比較命令は gt_n であり、 結果により unless_i 命令で、別のラベルにジャンプする
  • +
diff -r 642787982a80 -r 4b1eb4d69695 slide.md --- a/slide.md Fri Apr 19 18:24:04 2019 +0900 +++ b/slide.md Fri Apr 19 18:53:12 2019 +0900 @@ -203,7 +203,7 @@ ```perl6 sub add_test($n){ - mu $sum := 0; + my $sum := 0; while ( $n > 1) { $sum := $sum + $n; --$n; @@ -214,11 +214,23 @@ say(add_test(10000)); ``` -## NQPとオペコード +## NQP - NQPはPerl6の中で一番レイヤーが低い言語 - その為、 実行するVMのオペコード(処理単位)を使用することができる +- NQPオペコードは、 Perl6の内部の抽象構文木でも使用されている +- また、 Perl6と同様に型を指定することが可能 +```perl6 +sub add_test(int $n){ + mu $sum := 0; + while nqp::isgt_i($n,1) { + $sum := nqp::add_i($sum,$n); + $n := nqp::sub_i($n,1); + } + return $sum; +} +``` ## NQPとMoarVM - NQPそのものは実行することはできない @@ -238,7 +250,122 @@ - LuaJITなどを利用したJITコンパイルなども可能 - Perl6やNQPは、MoarVMに対してライブラリなどを設定して起動する + + ## バイトコード - Perl6も、Rakudo/NQPはバイトコードに変換され、 バイトコードをVMが実行する -- バイトコード実行部分は、 命令に対応するバイト列を読み込み、 解釈し、 次の命令を読み取ることを繰り返す +- Perl6/NQPはバイトコードにコンパイルすることが可能 + - 直接実行することはできない + +``` +$nqp --target=mbc --output=fib.moarvm fib.nqp +``` + +## バイトコードとMoarVM + + +- MoarVMバイトコードはMoarVMの実行バイナリ `moar` でディスアセンブルすることが可能 + + +``` + annotation: add_test.nqp:1 +00003 const_i64_16 loc_2_int, 0 +00004 hllboxtype_i loc_3_obj +00005 box_i loc_3_obj, loc_2_int, loc_3_obj +00006 set loc_1_obj, loc_3_obj + label_1: +00007 decont loc_3_obj, loc_0_obj +00008 smrt_numify loc_4_num, loc_3_obj +00009 const_i64_16 loc_2_int, 1 +00010 coerce_in loc_5_num, loc_2_int +00011 gt_n loc_2_int, loc_4_num, loc_5_num +00012 unless_i loc_2_int, label_2(00031) +00013 osrpoint + annotation: add_test.nqp:3 +00014 decont loc_3_obj, loc_1_obj +00015 smrt_numify loc_5_num, loc_3_obj +00016 decont loc_3_obj, loc_0_obj +00017 smrt_numify loc_4_num, loc_3_obj +00018 add_n loc_4_num, loc_5_num, loc_4_num +00019 hllboxtype_n loc_3_obj +00020 box_n loc_3_obj, loc_4_num, loc_3_obj +00021 set loc_1_obj, loc_3_obj +00022 decont loc_3_obj, loc_0_obj +00023 smrt_numify loc_4_num, loc_3_obj +00024 coerce_ni loc_6_int, loc_4_num +00025 const_i64_16 loc_7_int, 1 +00026 sub_i loc_7_int, loc_6_int, loc_7_int +00027 hllboxtype_i loc_3_obj +00028 box_i loc_3_obj, loc_7_int, loc_3_obj +00029 set loc_0_obj, loc_3_obj +00030 goto label_1(00007) +``` + +## NQPとバイトコードの対応 + +``` +say(add_test(10000)); +``` +``` + annotation: add_test.nqp:1 + label_1: +00020 getlex_no loc_7_obj, '&say' +00021 decont loc_7_obj, loc_7_obj +00022 const_s loc_3_str, '&add_test' +00023 getlexstatic_o loc_8_obj, loc_3_str +00024 decont loc_8_obj, loc_8_obj +00025 const_i64_16 loc_5_int, 10000 +00026 prepargs Callsite_1 +00027 arg_i 0, loc_5_int +00028 invoke_o loc_8_obj, loc_8_obj +00029 prepargs Callsite_0 +00030 arg_o 0, loc_8_obj +00031 invoke_v loc_7_obj +00032 null loc_7_obj +00033 return_o loc_7_obj +``` + +- Perl6の変数は直接実態を参照せず、中身が入っているコンテナを参照するようになっている。 +- その為 `decont` 命令で、コンテナの中身をレジスタに設定する必要がある +- `const_i64_16` などは64bitの数という意味で、 `int` 型としてレジスタに登録している +- `prepargs` で引数の確認を行い, `invoke_o` で実際にサブルーチンに移行する + +## NQPとバイトコードの対応 + +``` +my $sum := 0; +``` + +``` + annotation: add_test.nqp:1 +00003 const_i64_16 loc_2_int, 0 +00004 hllboxtype_i loc_3_obj +00005 box_i loc_3_obj, loc_2_int, loc_3_obj +00006 set loc_1_obj, loc_3_obj +``` + +- まず `loc_2` レジスタをint型の整数0で初期化する +- 変数 `$sum` はint型の指定がないので、 obj型で登録しなければならない +- その為, 整数として登録された `loc_2` から、 obj型に一旦キャストし、 `loc_3` レジスタに設定したものを、 `loc_1` レジスタに設定する + +## NQPとバイトコードの対応 + +``` + while ( $n > 1) { +``` + +``` + label_1: +00007 decont loc_3_obj, loc_0_obj +00008 smrt_numify loc_4_num, loc_3_obj +00009 const_i64_16 loc_2_int, 1 +00010 coerce_in loc_5_num, loc_2_int +00011 gt_n loc_2_int, loc_4_num, loc_5_num +00012 unless_i loc_2_int, label_2(00031) +00013 osrpoint +``` + +- 変数 `$n` と 整数 `1` を大小比較する為、 まず `$n` から値を取り出す +− 比較にもint型の指定がない為、 `num` 型にキャストし、 `num` 型のレジスタでの大小を比較する +- 比較命令は `gt_n` であり、 結果により `unless_i` 命令で、別のラベルにジャンプする diff -r 642787982a80 -r 4b1eb4d69695 slide.pdf.html --- a/slide.pdf.html Fri Apr 19 18:24:04 2019 +0900 +++ b/slide.pdf.html Fri Apr 19 18:53:12 2019 +0900 @@ -428,7 +428,7 @@

NQPスクリプト(nまでの整数の和)

sub add_test($n){
-    mu $sum := 0;
+    my $sum := 0;
     while ( $n > 1) {
         $sum := $sum + $n;
         --$n;
@@ -445,13 +445,25 @@
 
 
-

NQPとオペコード

+

NQP

  • NQPはPerl6の中で一番レイヤーが低い言語
  • その為、 実行するVMのオペコード(処理単位)を使用することができる
  • +
  • NQPオペコードは、 Perl6の内部の抽象構文木でも使用されている
  • +
  • また、 Perl6と同様に型を指定することが可能
+
sub add_test(int $n){
+    mu $sum := 0;
+    while nqp::isgt_i($n,1) {
+        $sum := nqp::add_i($sum,$n);
+        $n   := nqp::sub_i($n,1);
+    }
+    return $sum;
+}
+
+
@@ -512,9 +524,147 @@

バイトコード

  • Perl6も、Rakudo/NQPはバイトコードに変換され、 バイトコードをVMが実行する
  • -
  • バイトコード実行部分は、 命令に対応するバイト列を読み込み、 解釈し、 次の命令を読み取ることを繰り返す
  • +
  • Perl6/NQPはバイトコードにコンパイルすることが可能 +
      +
    • 直接実行することはできない
    • +
    +
  • +
+ +
$nqp --target=mbc --output=fib.moarvm fib.nqp
+
+ + + + + +
+ +

バイトコードとMoarVM

+ +
    +
  • MoarVMバイトコードはMoarVMの実行バイナリ moar でディスアセンブルすることが可能
+
     annotation: add_test.nqp:1
+00003      const_i64_16       loc_2_int, 0
+00004      hllboxtype_i       loc_3_obj
+00005      box_i              loc_3_obj, loc_2_int, loc_3_obj
+00006      set                loc_1_obj, loc_3_obj
+     label_1:
+00007      decont             loc_3_obj, loc_0_obj
+00008      smrt_numify        loc_4_num, loc_3_obj
+00009      const_i64_16       loc_2_int, 1
+00010      coerce_in          loc_5_num, loc_2_int
+00011      gt_n               loc_2_int, loc_4_num, loc_5_num
+00012      unless_i           loc_2_int, label_2(00031)
+00013      osrpoint
+     annotation: add_test.nqp:3
+00014      decont             loc_3_obj, loc_1_obj
+00015      smrt_numify        loc_5_num, loc_3_obj
+00016      decont             loc_3_obj, loc_0_obj
+00017      smrt_numify        loc_4_num, loc_3_obj
+00018      add_n              loc_4_num, loc_5_num, loc_4_num
+00019      hllboxtype_n       loc_3_obj
+00020      box_n              loc_3_obj, loc_4_num, loc_3_obj
+00021      set                loc_1_obj, loc_3_obj
+00022      decont             loc_3_obj, loc_0_obj
+00023      smrt_numify        loc_4_num, loc_3_obj
+00024      coerce_ni          loc_6_int, loc_4_num
+00025      const_i64_16       loc_7_int, 1
+00026      sub_i              loc_7_int, loc_6_int, loc_7_int
+00027      hllboxtype_i       loc_3_obj
+00028      box_i              loc_3_obj, loc_7_int, loc_3_obj
+00029      set                loc_0_obj, loc_3_obj
+00030      goto               label_1(00007)
+
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
say(add_test(10000));
+
+ +
     annotation: add_test.nqp:1
+     label_1:
+00020      getlex_no          loc_7_obj, '&say'
+00021      decont             loc_7_obj, loc_7_obj
+00022      const_s            loc_3_str, '&add_test'
+00023      getlexstatic_o     loc_8_obj, loc_3_str
+00024      decont             loc_8_obj, loc_8_obj
+00025      const_i64_16       loc_5_int, 10000
+00026      prepargs           Callsite_1
+00027      arg_i              0, loc_5_int
+00028      invoke_o           loc_8_obj, loc_8_obj
+00029      prepargs           Callsite_0
+00030      arg_o              0, loc_8_obj
+00031      invoke_v           loc_7_obj
+00032      null               loc_7_obj
+00033      return_o           loc_7_obj
+
+ +
    +
  • Perl6の変数は直接実態を参照せず、中身が入っているコンテナを参照するようになっている。
  • +
  • その為 decont 命令で、コンテナの中身をレジスタに設定する必要がある
  • +
  • const_i64_16 などは64bitの数という意味で、 int 型としてレジスタに登録している
  • +
  • prepargs で引数の確認を行い, invoke_o で実際にサブルーチンに移行する
  • +
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
my $sum := 0;
+
+ +
     annotation: add_test.nqp:1
+00003      const_i64_16       loc_2_int, 0
+00004      hllboxtype_i       loc_3_obj
+00005      box_i              loc_3_obj, loc_2_int, loc_3_obj
+00006      set                loc_1_obj, loc_3_obj
+
+ +
    +
  • まず loc_2 レジスタをint型の整数0で初期化する
  • +
  • 変数 $sum はint型の指定がないので、 obj型で登録しなければならない
  • +
  • その為, 整数として登録された loc_2 から、 obj型に一旦キャストし、 loc_3 レジスタに設定したものを、 loc_1 レジスタに設定する
  • +
+ + + +
+ +
+ +

NQPとバイトコードの対応

+ +
    while ( $n > 1) {
+
+ +
     label_1:
+00007      decont             loc_3_obj, loc_0_obj
+00008      smrt_numify        loc_4_num, loc_3_obj
+00009      const_i64_16       loc_2_int, 1
+00010      coerce_in          loc_5_num, loc_2_int
+00011      gt_n               loc_2_int, loc_4_num, loc_5_num
+00012      unless_i           loc_2_int, label_2(00031)
+00013      osrpoint
+
+ +
    +
  • 変数 $n と 整数 1 を大小比較する為、 まず $n から値を取り出す
  • +
  • 比較にもint型の指定がない為、 num 型にキャストし、 num 型のレジスタでの大小を比較する
  • +
  • 比較命令は gt_n であり、 結果により unless_i 命令で、別のラベルにジャンプする
  • +