comparison slide.html @ 18:1fc9d0bd924f default tip

update
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sat, 20 Apr 2019 18:06:35 +0900
parents a176ea5c0264
children
comparison
equal deleted inserted replaced
17:a176ea5c0264 18:1fc9d0bd924f
137 <ul> 137 <ul>
138 <li>現在は別の言語として開発がそれぞれ進んでいる</li> 138 <li>現在は別の言語として開発がそれぞれ進んでいる</li>
139 </ul> 139 </ul>
140 </li> 140 </li>
141 <li>仕様と実装が分離しており, 現在はテストが仕様となっている</li> 141 <li>仕様と実装が分離しており, 現在はテストが仕様となっている</li>
142 <li>実装は歴史上複数存在しているが,主流な実装はRakudo</li> 142 <li>実装は歴史上複数存在しているが,主流な実装はRakudo
143 <ul>
144 <li>Haskellで実装されたPugs</li>
145 <li>Pythonとの共同基板を目指したParrot</li>
146 </ul>
147 </li>
143 <li>言語的にはスクリプト言語であり, 漸進的型付き言語</li> 148 <li>言語的にはスクリプト言語であり, 漸進的型付き言語</li>
144 <li>動作環境は、独自のVMのMoarVM, JVM、一部JavaScript上で動作する</li> 149 <li>動作環境は、独自のVMのMoarVM, JVM、一部JavaScript上で動作する</li>
145 </ul> 150 </ul>
146 151
147 <p><img src="fig/2000px-Camelia.svg.png" alt="" style="width: 31%; height: auto;" /></p> 152 <p><img src="fig/2000px-Camelia.svg.png" alt="" style="width: 31%; height: auto;" /></p>
382 387
383 <div class='slide'> 388 <div class='slide'>
384 <!-- _S9SLIDE_ --> 389 <!-- _S9SLIDE_ -->
385 <h2 id="rakudoの構成図">Rakudoの構成図</h2> 390 <h2 id="rakudoの構成図">Rakudoの構成図</h2>
386 391
387 <p><img src="fig/Rakudo_System_overview.png" alt="" /></p> 392 <p><img src="fig/Rakudo_overview.svg" alt="" /></p>
388 393
389 <p>(http://brrt-to-the-future.blogspot.com/2015/03/advancing-jit-compiler.html)</p> 394 <p>(http://brrt-to-the-future.blogspot.com/2015/03/advancing-jit-compiler.html)</p>
390 395
391 396
392 397
747 <pre><code>00008 smrt_numify loc_4_num, loc_3_obj 752 <pre><code>00008 smrt_numify loc_4_num, loc_3_obj
748 </code></pre> 753 </code></pre>
749 754
750 <ul> 755 <ul>
751 <li><code>smrt_numify</code> はレジスタ上のオブジェクトを、 num型に変換し、 別のレジスタに登録する命令</li> 756 <li><code>smrt_numify</code> はレジスタ上のオブジェクトを、 num型に変換し、 別のレジスタに登録する命令</li>
752 <li>今回の整数の比較では、 int型の強制がない為、 数値として比較するためにnum型にキャストしている</li> 757 <li>今回の整数の比較では、 int型の強制がない為、 数値として比較するためにn64型にキャストしている
758 <ul>
759 <li>numはn64型であり、 64ビットの浮動小数点定数の意味</li>
760 </ul>
761 </li>
753 </ul> 762 </ul>
754 763
755 <p><img src="fig/perl6_num_convert.svg" alt="" /></p> 764 <p><img src="fig/perl6_num_convert.svg" alt="" /></p>
765
766
767
768 </div>
769
770 <div class='slide'>
771 <!-- _S9SLIDE_ -->
772 <h2 id="const_i64_16とcoerece_in">const_i64_16とcoerece_in</h2>
773
774 <pre><code> while ( $n &gt; 1) {
775 </code></pre>
776
777 <pre><code>00009 const_i64_16 loc_2_int, 1
778 00010 coerce_in loc_5_num, loc_2_int
779 </code></pre>
780 <ul>
781 <li>64ビット整数として1をレジスタ <code>loc_2</code> に設定する</li>
782 <li>その後、 numでの比較のためにキャストし, <code>loc_5</code> レジスタに設定している</li>
783 </ul>
784
785
786
787 </div>
788
789 <div class='slide'>
790 <!-- _S9SLIDE_ -->
791 <h2 id="比較とif文の判定">比較とif文の判定</h2>
792
793 <pre><code> while ( $n &gt; 1) {
794 </code></pre>
795
796 <pre><code>00011 gt_n loc_2_int, loc_4_num, loc_5_num
797 00012 unless_i loc_2_int, label_2(00031)
798 </code></pre>
799
800 <ul>
801 <li><code>gt_n</code> で <code>loc_4</code> (nが入っている) レジスタと <code>loc_5</code> (1が入っているレジスタ)を比較する
802 <ul>
803 <li>結果により <code>loc_2</code> レジスタに真偽値がint型で代入される</li>
804 </ul>
805 </li>
806 <li>その結果を <code>unless_i</code> で読み取り、 値が偽であったら <code>label_2(00031)</code> にジャンプする</li>
807 </ul>
808
809
810
811 </div>
812
813 <div class='slide'>
814 <!-- _S9SLIDE_ -->
815 <h2 id="c言語での実装へ">C言語での実装へ</h2>
816 <ul>
817 <li>今まではスクリプトレベルでの実装を見てきました</li>
818 <li>スクリプトが実行されるVMの実装をCレベルで見ていきましょう</li>
819 </ul>
756 820
757 821
758 822
759 </div> 823 </div>
760 824
768 <li>命令部分を実行する</li> 832 <li>命令部分を実行する</li>
769 <li>バイトコード列を次に進め、繰り返す</li> 833 <li>バイトコード列を次に進め、繰り返す</li>
770 </ol> 834 </ol>
771 835
772 <ul> 836 <ul>
773 <li>この部分の実装は大体次のような処理をしている</li> 837 <li>この部分の実装は大体次のようなパターンで記述されている</li>
774 </ul> 838 </ul>
775 839
776 840
777 841
778 </div> 842 </div>
784 <ul> 848 <ul>
785 <li>命令に対応するバイトコードを数値に変換できるようにし、 switch-case文で分岐させる</li> 849 <li>命令に対応するバイトコードを数値に変換できるようにし、 switch-case文で分岐させる</li>
786 <li>実行のたびにループで先頭に戻り、次の命令を計算する必要があるので低速</li> 850 <li>実行のたびにループで先頭に戻り、次の命令を計算する必要があるので低速</li>
787 </ul> 851 </ul>
788 852
789 <pre><code> 853 <pre><code> while( pc != NULL) {
854 switch(pc){
855 case ADD_INSTRUCTION:
856 // instruction....
857 break;
858 case SUBD_INSTRUCTION:
859 // instruction....
860 break;
861 }
862 }
790 </code></pre> 863 </code></pre>
791 864
792 865
793 866
794 </div> 867 </div>
797 <!-- _S9SLIDE_ --> 870 <!-- _S9SLIDE_ -->
798 <h2 id="cコンパイラのラベルgotoを使うケース">Cコンパイラのラベルgotoを使うケース</h2> 871 <h2 id="cコンパイラのラベルgotoを使うケース">Cコンパイラのラベルgotoを使うケース</h2>
799 872
800 <ul> 873 <ul>
801 <li>巨大なcase文とループではなく、 次の命令の実行場所に直接jmpで移動する</li> 874 <li>巨大なcase文とループではなく、 次の命令の実行場所に直接jmpで移動する</li>
875 <li>GCC拡張でサポートしている場合「<code>&amp;&amp;ラベル名</code> 」でラベルのアドレスが取得できる
876 <ul>
877 <li>取得したアドレスに対して「goto アドレス」でgoto文でjmpする</li>
878 </ul>
879 </li>
802 <li>次の命令に対応するラベルを取得する必要があるが、 ループする必要がなく高速</li> 880 <li>次の命令に対応するラベルを取得する必要があるが、 ループする必要がなく高速</li>
803 <li>ラベルgotoであり、 Cコンパイラの拡張機能として搭載されている 881 <li>ラベルgotoであり、 Cコンパイラの拡張機能として搭載されている
804 <ul> 882 <ul>
805 <li>gccおよびLLVM/clangには実装されている</li> 883 <li>gccおよびLLVM/clangには実装されている</li>
806 </ul> 884 </ul>
807 </li> 885 </li>
808 </ul> 886 </ul>
809 887
810 <pre><code> 888 <pre><code> static const void *CODES[] = {&amp;&amp;ADD_INSTRUCTION, &amp;&amp;SUB_INSTRCUTION};
889
890 goto *CODES[pc];
891
892 ADD_INSTRUCTION:
893 // instruction...
894 pc++;
895 goto *CODES[pc];
896
897 SUB_INSTRUCTION:
898 // instruction...
899 pc++;
900 goto *CODES[pc];
811 </code></pre> 901 </code></pre>
812 902
813 903
814 904
815 </div> 905 </div>
823 <ul> 913 <ul>
824 <li>この判断はマクロで処理をしている</li> 914 <li>この判断はマクロで処理をしている</li>
825 </ul> 915 </ul>
826 </li> 916 </li>
827 <li>一般的にはラベルgotoの方が高速である為、他のスクリプト言語でもラベルgotoが使われている</li> 917 <li>一般的にはラベルgotoの方が高速である為、他のスクリプト言語でもラベルgotoが使われている</li>
918 </ul>
919
920
921
922 </div>
923
924 <div class='slide'>
925 <!-- _S9SLIDE_ -->
926 <h2 id="moarvmのc言語での実装">MoarVMのC言語での実装</h2>
927
928 <ul>
929 <li><a href="https://github.com/MoarVM/MoarVM">GitHub上にリポジトリ</a>がある</li>
930 <li><code>src/core/interp.c</code> がバイトコードインタプリタの実装コード</li>
931 <li>この中でマクロを使いつつ、 バイトコードに対応した命令を処理している</li>
932 <li><code>MVM_interp_run</code>が実際にバイトコードを解釈している</li>
933 </ul>
934
935 <pre><code>/* This is the interpreter run loop. We have one of these per thread. */
936 void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContext *, void *), void *invoke_data) {
937 #if MVM_CGOTO
938 #include "oplabels.h"
939 #endif
940
941 /* Points to the place in the bytecode right after the current opcode. */
942 /* See the NEXT_OP macro for making sense of this */
943 MVMuint8 *cur_op = NULL;
944
945 /* The current frame's bytecode start. */
946 MVMuint8 *bytecode_start = NULL;
947
948 /* Points to the base of the current register set for the frame we
949 * are presently in. */
950 MVMRegister *reg_base = NULL;
951
952 /* Points to the current compilation unit. */
953 MVMCompUnit *cu = NULL;
954
955 /* The current call site we're constructing. */
956 MVMCallsite *cur_callsite = NULL;
957
958 /* Stash addresses of current op, register base and SC deref base
959 * in the TC; this will be used by anything that needs to switch
960 * the current place we're interpreting. */
961 tc-&gt;interp_cur_op = &amp;cur_op;
962 tc-&gt;interp_bytecode_start = &amp;bytecode_start;
963 tc-&gt;interp_reg_base = &amp;reg_base;
964 tc-&gt;interp_cu = &amp;cu;
965
966 /* With everything set up, do the initial invocation (exactly what this does
967 * varies depending on if this is starting a new thread or is the top-level
968 * program entry point). */
969 initial_invoke(tc, invoke_data);
970 </code></pre>
971
972
973
974 </div>
975
976 <div class='slide'>
977 <!-- _S9SLIDE_ -->
978 <h2 id="moarvmのレジスタ構成">MoarVMのレジスタ構成</h2>
979
980 <ul>
981 <li>レジスタはそれぞれの型を共用体のデータ構造で持っている</li>
982 <li>型名は各命令の接尾辞に対応している</li>
983 </ul>
984
985 <pre><code>/* Different views of a register. */
986 union MVMRegister {
987 MVMObject *o;
988 MVMString *s;
989 MVMint8 i8;
990 MVMuint8 u8;
991 MVMint16 i16;
992 MVMuint16 u16;
993 MVMint32 i32;
994 MVMuint32 u32;
995 MVMint64 i64;
996 MVMuint64 u64;
997 MVMnum32 n32;
998 MVMnum64 n64;
999 };
1000 </code></pre>
1001
1002
1003
1004 </div>
1005
1006 <div class='slide'>
1007 <!-- _S9SLIDE_ -->
1008 <h2 id="mvm_interp_runの登場人物">MVM_interp_runの登場人物</h2>
1009
1010 <ul>
1011 <li><code>cur_op</code> が読み取るのバイトコード列の先頭ポインタを保存している</li>
1012 <li><code>op</code> が現在実行する命令の数値が入っている</li>
1013 <li><code>reg_base</code> がMoarVMのレジスタの集合配列</li>
1014 </ul>
1015
1016 <pre><code> /* Points to the place in the bytecode right after the current opcode. */
1017 /* See the NEXT_OP macro for making sense of this */
1018 MVMuint8 *cur_op = NULL;
1019
1020 /* The current frame's bytecode start. */
1021 MVMuint8 *bytecode_start = NULL;
1022
1023 /* Points to the base of the current register set for the frame we
1024 * are presently in. */
1025 MVMRegister *reg_base = NULL;
1026 </code></pre>
1027
1028
1029
1030 </div>
1031
1032 <div class='slide'>
1033 <!-- _S9SLIDE_ -->
1034 <h2 id="mvm_interp_runメインループ">MVM_interp_runメインループ</h2>
1035
1036 <ul>
1037 <li><code>runloop</code>がメインのループで処理を行っている
1038 <ul>
1039 <li><code>DISPATCH</code>部分で命令をバイトコード列から取り出している</li>
1040 </ul>
1041 </li>
1042 </ul>
1043
1044 <pre><code> /* Enter runloop. */
1045 runloop: {
1046 MVMuint16 op;
1047
1048 #if MVM_TRACING
1049 if (tracing_enabled) {
1050 char *trace_line;
1051 trace_line = MVM_exception_backtrace_line(tc, tc-&gt;cur_frame, 0, cur_op);
1052 fprintf(stderr, "Op %d%s\n", (int)*((MVMuint16 *)cur_op), trace_line);
1053 /* slow tracing is slow. Feel free to speed it. */
1054 MVM_free(trace_line);
1055 }
1056 #endif
1057
1058 /* The ops should be in the same order here as in the oplist file, so
1059 * the compiler can can optimise the switch properly. To check if they
1060 * are in the same order as the oplist use the
1061 * tools/compare-oplist-interp-order.sh helper script. */
1062 DISPATCH(NEXT_OP) {
1063 OP(no_op):
1064 goto NEXT;
1065 OP(const_i8):
1066 OP(const_i16):
1067 OP(const_i32):
1068 MVM_exception_throw_adhoc(tc, "const_iX NYI");
1069 OP(const_i64):
1070 GET_REG(cur_op, 0).i64 = MVM_BC_get_I64(cur_op, 2);
1071 cur_op += 10;
1072 goto NEXT;
1073 </code></pre>
1074
1075
1076
1077 </div>
1078
1079 <div class='slide'>
1080 <!-- _S9SLIDE_ -->
1081 <h2 id="mvm_interp_runメインループ-1">MVM_interp_runメインループ</h2>
1082
1083 <ul>
1084 <li><code>DISPATCH</code>はマクロになっている
1085 <ul>
1086 <li>ラベルgotoが使えるケースはDISPATCHは何も意味を持たない</li>
1087 <li>使えない場合はswitch文に展開される
1088 <ul>
1089 <li><code>op</code> に実行する命令の数値が格納されているので、 これに応じてswitchで飛ぶ</li>
1090 </ul>
1091 </li>
1092 </ul>
1093 </li>
1094 </ul>
1095
1096 <pre><code>#if MVM_CGOTO
1097 #define DISPATCH(op)
1098 #define OP(name) OP_ ## name
1099 #define NEXT *LABELS[NEXT_OP]
1100 #else
1101 #define DISPATCH(op) switch (op)
1102 #define OP(name) case MVM_OP_ ## name
1103 #define NEXT runloop
1104 #endif
1105 </code></pre>
1106
1107
1108
1109 </div>
1110
1111 <div class='slide'>
1112 <!-- _S9SLIDE_ -->
1113 <h2 id="mvm_interp_runメインループ-2">MVM_interp_runメインループ</h2>
1114
1115 <ul>
1116 <li><code>OP</code> が命令のスコープを切るマクロとなっている
1117 <ul>
1118 <li>gotoが使える場合
1119 <ul>
1120 <li><code>##name</code> に展開され、 それぞれの命令の名前を持つラベルになる</li>
1121 </ul>
1122 </li>
1123 <li>gotoが使えない場合
1124 <ul>
1125 <li>case文に展開される</li>
1126 </ul>
1127 </li>
1128 </ul>
1129 </li>
1130 </ul>
1131
1132 <pre><code>#if MVM_CGOTO
1133 #define DISPATCH(op)
1134 #define OP(name) OP_ ## name
1135 #define NEXT *LABELS[NEXT_OP]
1136 #else
1137 #define DISPATCH(op) switch (op)
1138 #define OP(name) case MVM_OP_ ## name
1139 #define NEXT runloop
1140 #endif
1141 </code></pre>
1142
1143
1144
1145 </div>
1146
1147 <div class='slide'>
1148 <!-- _S9SLIDE_ -->
1149 <h2 id="mvm_interp_runメインループ-3">MVM_interp_runメインループ</h2>
1150
1151 <ul>
1152 <li>次の命令には <code>NEXT</code> マクロで移動する
1153 <ul>
1154 <li>gotoが使える場合
1155 <ul>
1156 <li>次のラベルに対応したアドレスを配列LABELSから取り出しgotoする</li>
1157 </ul>
1158 </li>
1159 <li>gotoが使えない場合
1160 <ul>
1161 <li><code>runloop</code>に対してgotoする(先頭へのループ)</li>
1162 </ul>
1163 </li>
1164 </ul>
1165 </li>
1166 </ul>
1167
1168 <pre><code>#if MVM_CGOTO
1169 #define DISPATCH(op)
1170 #define OP(name) OP_ ## name
1171 #define NEXT *LABELS[NEXT_OP]
1172 #else
1173 #define DISPATCH(op) switch (op)
1174 #define OP(name) case MVM_OP_ ## name
1175 #define NEXT runloop
1176 #endif
1177 </code></pre>
1178
1179
1180
1181 </div>
1182
1183 <div class='slide'>
1184 <!-- _S9SLIDE_ -->
1185 <h2 id="それぞれの命令の実装">それぞれの命令の実装</h2>
1186
1187 <ul>
1188 <li>マクロ <code>GET_REG</code> でレジスタ情報を取得する
1189 <ul>
1190 <li>末尾で型を指定する</li>
1191 </ul>
1192 </li>
1193 <li>よしなに処理をした後に、バイトコード列 <code>cur_op</code> をインクリメントする
1194 <ul>
1195 <li>計算機のプログラムカウンタを進めることに対応する</li>
1196 </ul>
1197 </li>
1198 </ul>
1199
1200 <pre><code> OP(add_i):
1201 GET_REG(cur_op, 0).i64 = GET_REG(cur_op, 2).i64 + GET_REG(cur_op, 4).i64;
1202 cur_op += 6;
1203 goto NEXT;
1204 OP(sub_i):
1205 GET_REG(cur_op, 0).i64 = GET_REG(cur_op, 2).i64 - GET_REG(cur_op, 4).i64;
1206 cur_op += 6;
1207 goto NEXT;
1208 OP(mul_i):
1209 GET_REG(cur_op, 0).i64 = GET_REG(cur_op, 2).i64 * GET_REG(cur_op, 4).i64;
1210 cur_op += 6;
1211 goto NEXT;
1212 </code></pre>
1213
1214
1215
1216 </div>
1217
1218 <div class='slide'>
1219 <!-- _S9SLIDE_ -->
1220 <h2 id="本日の展示について">本日の展示について</h2>
1221
1222 <ul>
1223 <li>現在当研究室で開発しているContinuationBasedC(CbC)で一部Perl6の処理系を書いています</li>
1224 <li>また、 CbCを用いたGearsOSの展示も行っています</li>
1225 </ul>
1226
1227
1228
1229 </div>
1230
1231 <div class='slide'>
1232 <!-- _S9SLIDE_ -->
1233 <h2 id="まとめ">まとめ</h2>
1234 <ul>
1235 <li>Perl6の内部構造に迫りました</li>
1236 <li>スクリプト言語の中身も通常の計算機と同じような処理をしています</li>
1237 <li>OSSなので皆さん読んで改造してみましょう!!</li>
828 </ul> 1238 </ul>
829 1239
830 </div> 1240 </div>
831 1241
832 1242