Mercurial > hg > Events > OSC2019
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 > 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 > 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>&&ラベル名</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[] = {&&ADD_INSTRUCTION, &&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->interp_cur_op = &cur_op; | |
962 tc->interp_bytecode_start = &bytecode_start; | |
963 tc->interp_reg_base = &reg_base; | |
964 tc->interp_cu = &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->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 |