comparison slides/2018/06/26/slide.md @ 47:32e35be2ce71

auto-Update generated slides by script
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Tue, 26 Jun 2018 22:41:26 +0900
parents
children
comparison
equal deleted inserted replaced
46:8972d59ad904 47:32e35be2ce71
1 title: CbCによるMoarVMの改良
2 author: Takahiro Shimizu
3 profile:
4 lang: Japanese
5
6
7 # 研究目的
8 - Perl5の後継言語として開発されているPerl6はMoarVMと呼ばれるVMを搭載している.
9 - Perl6はMoarVM,JVM,JavaScript上で動くRakudoと呼ばれる実装と,コンパイラ開発者用のサブセットであるNQPが主な実装となっている.
10 - 現在Perl6及びMoarVMは全体的な速度がPerl5と比較し低下しており,実務として利用できるレベルに達していない.
11 - さらにPerl6の実装自体巨大なcase-switch文など見通しが悪くなっている.
12 - この問題を解決するために現在当研究室で開発している継続を中心にしたContinuation based Cを用いて改良を行う
13 - CbCの設計理念からVMの実装と親和性が高い事も推測できる為,実際にCbCを用いてどのようにVMが実装できるかを検証する
14
15 # 今週の進捗
16 * 暑くて死んでました
17 * OSCの資料をwebにあげました
18 * Perl6のコンパイルとJITのトレースをしました
19 * 院試対策し始めてます
20
21 # お知らせ
22
23 * [並列研の公式page](http://www.cr.ie.u-ryukyu.ac.jp/)にスライド置き場を作りました
24 * CSS力はなかった
25
26
27 # Perl6のbuild
28
29 * JITのトレースがしたかったのでPerl6をbuildしました
30
31 ./Configure.pl --prefix=/Users/anatofuz/workspace/cr/Basic/build_perl6 --backends=moar --with-nqp=//Users/anatofuz/workspace/cr/Basic/build_perl6/bin/nqp
32
33 # Perl6-lldb-m
34
35 * `Perl6-lldb-m`というデバッグ用のスクリプトが生成されていた
36
37 ```
38 #!/bin/sh
39 /Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar --execname="$0" --libpath="." --libpath="blib" --libpath="/Users/anatofuz/workspace/cr/Basic/build_perl6/share/nqp/lib" --libpath="/Users/anatofuz/workspace/cr/Basic/build_perl6/share/nqp/lib" /Users/anatofuz/workspace/cr/Basic/perl6/MoarVM_basic/rakudo/perl6.moarvm --nqp-lib=blib -e '
40 say "=" x 96;
41
42 say "This is Rakudo Perl 6 running in the LLVM debugger, which often allows the user to generate useful back-\ntraces to debug or report issues in Rakudo, the MoarVM backend or the currently running code.\n";
43
44 unless $*VM.config<ccdebugflags> { say "The currently used MoarVM backend is not compiled with debugging symbols, you might want to\nreconfigure and reinstall MoarVM with --debug enabled.\n" }
45
46 say "This Rakudo version is $*PERL.compiler.version() built on MoarVM version $*VM.version(),";
47 say "running on $*DISTRO.gist() / $*KERNEL.gist()\n";
48
49 say "Type `bt full` to generate a backtrace if applicable, type `q` to quit or `help` for help.";
50
51 say "-" x 96;'
52 lldb /Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar -- --execname="$0" --libpath="." --libpath="blib" --libpath="/Users/anatofuz/workspace/cr/Basic/build_perl6/share/nqp/lib" --libpath="/Users/anatofuz/workspace/cr/Basic/build_perl6/share/nqp/lib" /Users/anatofuz/workspace/cr/Basic/perl6/MoarVM_basic/rakudo/perl6.moarvm --nqp-lib=blib "$@"
53 ```
54
55 # JITのトレース
56
57 * 何も実行しないとBreakpointに引っかかる
58
59 ```
60 $ ./perl6-lldb-m
61 ================================================================================================
62 This is Rakudo Perl 6 running in the LLVM debugger, which often allows the user to generate useful back-
63 traces to debug or report issues in Rakudo, the MoarVM backend or the currently running code.
64
65 This Rakudo version is 2018.04.1 built on MoarVM version 2018.04.1,
66 running on macosx (10.13.5) / darwin (17.6.0)
67
68 Type `bt full` to generate a backtrace if applicable, type `q` to quit or `help` for help.
69 ------------------------------------------------------------------------------------------------
70 b (lldb) target create "/Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar"
71 Current executable set to '/Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar' (x86_64).
72 (lldb) settings set -- target.run-args "--execname=./perl6-lldb-m" "--libpath=/Users/anatofuz/workspace/cr/Basic/build_perl6/share/nqp/lib" "--libpath=/Users/anatofuz/workspace/cr/Basic/build_perl6/share/perl6/lib" "--libpath=/Users/anatofuz/workspace/cr/Basic/build_perl6/share/perl6/runtime" "/Users/anatofuz/workspace/cr/Basic/build_perl6/share/perl6/runtime/perl6.moarvm"
73 (lldb) b MVM_jit_compiler_init
74 Breakpoint 1: where = libmoar.dylib`MVM_jit_compiler_init + 20 at compile.c:17, address = 0x00000000001e4d54
75 (lldb) run
76 Process 4185 launched: '/Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar' (x86_64)
77 Process 4185 stopped
78 * thread #2, stop reason = breakpoint 1.1
79 frame #0: 0x0000000100287d54 libmoar.dylib`MVM_jit_compiler_init(tc=0x000000010084db80, cl=0x0000700007fa1c60, jg=0x000000010345ca7a) at compile.c:17
80 14 static const MVMuint16 MAGIC_BYTECODE[] = { MVM_OP_sp_jit_enter, 0 };
81 15
82 16 void MVM_jit_compiler_init(MVMThreadContext *tc, MVMJitCompiler *cl, MVMJitGraph *jg) {
83 -> 17 MVMint32 num_globals = MVM_jit_num_globals();
84 18 /* Create dasm state */
85 19 dasm_init(cl, 2);
86 20 cl->dasm_globals = MVM_malloc(num_globals * sizeof(void*));
87 Target 0: (moar) stopped.
88 ```
89
90 # JIT用のコード
91
92 ```
93 #!/usr/bin/env perl6
94 use v6;
95
96 my @hoge = (1..300);
97
98 sub foo(@a){
99 @a[0] = @a.elems;
100 }
101
102 say foo(@hoge);
103 ```
104
105
106 ```
107 (lldb) run jit.p6
108 Process 4223 launched: '/Users/anatofuz/workspace/cr/Basic/build_perl6/bin/moar' (x86_64)
109 Unhandled exception: Bytecode stream corrupt (missing magic string)
110 Process 4223 exited with status = 1 (0x00000001)
111 ```
112
113 * Bytecode stream corruptのエラーが発生する
114
115 # missing magic string
116
117 * `src/core/bytecode.c` 135行目で定義されているエラーらしい
118
119 ```
120 /* Dissects the bytecode stream and hands back a reader pointing to the
121 * various parts of it. */
122 static ReaderState * dissect_bytecode(MVMThreadContext *tc, MVMCompUnit *cu) {
123 MVMCompUnitBody *cu_body = &cu->body;
124 ReaderState *rs = NULL;
125 MVMuint32 version, offset, size;
126
127 /* Sanity checks. */
128 if (cu_body->data_size < HEADER_SIZE)
129 MVM_exception_throw_adhoc(tc, "Bytecode stream shorter than header");
130 if (memcmp(cu_body->data_start, "MOARVM\r\n", 8) != 0)
131 MVM_exception_throw_adhoc(tc, "Bytecode stream corrupt (missing magic string)");
132 version = read_int32(cu_body->data_start, 8);
133 if (version < MIN_BYTECODE_VERSION)
134 MVM_exception_throw_adhoc(tc, "Bytecode stream version too low");
135 if (version > MAX_BYTECODE_VERSION)
136 MVM_exception_throw_adhoc(tc, "Bytecode stream version too high");
137
138 /* Allocate reader state. */
139 rs = (ReaderState *)MVM_calloc(1, sizeof(ReaderState));
140 rs->version = version;
141 rs->read_limit = cu_body->data_start + cu_body->data_size;
142 cu->body.bytecode_version = version;
143
144 /* Locate SC dependencies segment. */
145 offset = read_int32(cu_body->data_start, SCDEP_HEADER_OFFSET);
146 if (offset > cu_body->data_size) {
147 cleanup_all(tc, rs);
148 MVM_exception_throw_adhoc(tc, "Serialization contexts segment starts after end of stream");
149 }
150 rs->sc_seg = cu_body->data_start + offset;
151 rs->expected_scs = read_int32(cu_body->data_start, SCDEP_HEADER_OFFSET + 4);
152
153 ```
154
155 # エラーの原因
156
157 * `memcmp(cu_body->data_start, "MOARVM\r\n", 8) != 0` でMoarVMと文字列比較をしているが,この部分でスクリプトすべてが流れ込んでいた
158
159 ```
160 (lldb) p *cu_body
161 (MVMCompUnitBody) $1 = {
162 data_start = 0x00000001007e5000 "#!/usr/bin/env perl6\nuse v6;\n\nmy @hoge = (1..300);\n\nsub foo(@a){\n @a[0] = @a.elems;\n}\n\nsay foo(@hoge);\n"
163 data_size = 106
164 num_extops = 0
165 ```
166
167
168 #
169
170 ```
171 (MVMCompUnitBody) $2 = {
172 data_start = 0x00000001007e5000 "#!/usr/bin/env perl6\nuse v6;\n\nmy @hoge = (1..300);\n\nsub foo(@a){\n @a[0] = @a.elems;\n}\n\nsay foo(@hoge);\n"
173 data_size = 106
174 num_extops = 0
175 max_callsite_size = 0
176 coderefs = 0x0000000000000000
177 num_frames = 0
178 orig_frames = 0
179 main_frame = 0x0000000000000000
180 load_frame = 0x0000000000000000
181 deserialize_frame = 0x0000000000000000
182 callsites = 0x0000000000000000
183 num_callsites = 0
184 orig_callsites = 0
185 extops = 0x0000000000000000
186 strings = 0x0000000000000000
187 num_strings = 0
188 orig_strings = 0
189 string_heap_fast_table = 0x0000000000000000
190 string_heap_fast_table_top = 0
191 serialized_size = 0
192 string_heap_start = 0x0000000000000000 <no value available>
193 string_heap_read_limit = 0x0000000000000000 <no value available>
194 serialized = 0x0000000000000000 <no value available>
195 scs = 0x0000000000000000
196 num_scs = 0
197 deallocate = MVM_DEALLOCATE_NOOP
198 scs_to_resolve = 0x0000000000000000
199 sc_handle_idxs = 0x0000000000000000
200 hll_config = 0x0000000000000000
201 hll_name = 0x0000000000000000
202 filename = 0x0000000000000000
203 handle = 0x0000000000000000
204 inline_tweak_mutex = 0x000000010084e040
205 deserialize_frame_mutex = 0x0000000101017900
206 bytecode_version = 0
207 invoked = '\0'
208 }
209 ```
210
211 # cuの生成部分
212
213 * compunit.cの `MVM_cu_map_from_file`から読んでいる`MVM_cu_from_bytes`で生成している
214
215 ```
216 (lldb) f
217 frame #4: 0x00000001000d4238 libmoar.dylib`MVM_cu_map_from_file(tc=0x0000000100802100, filename="jit.p6") at compunit.c:64
218 61 }
219 62
220 63 /* Turn it into a compilation unit. */
221 -> 64 cu = MVM_cu_from_bytes(tc, (MVMuint8 *)block, (MVMuint32)size);
222 65 cu->body.handle = handle;
223 66 cu->body.deallocate = MVM_DEALLOCATE_UNMAP;
224 67 return cu;
225 ```
226
227 * 問題となっている箇所はこの時点で `block`に記録されている
228
229
230 # blockの生成部分
231
232 ```
233 33 /* Loads a compilation unit from a bytecode file, mapping it into memory. */
234 34 MVMCompUnit * MVM_cu_map_from_file(MVMThreadContext *tc, const char *filename) {
235 35 MVMCompUnit *cu = NULL;
236 36 void *block = NULL;
237 37 void *handle = NULL;
238 38 uv_file fd;
239 39 MVMuint64 size;
240 (lldb)
241 40 uv_fs_t req;
242 41
243 42 /* Ensure the file exists, and get its size. */
244 43 if (uv_fs_stat(tc->loop, &req, filename, NULL) < 0) {
245 44 MVM_exception_throw_adhoc(tc, "While looking for '%s': %s", filename, uv_strerror(req.result));
246 45 }
247 46
248 47 size = req.statbuf.st_size;
249 48
250 49 /* Map the bytecode file into memory. */
251 (lldb)
252 50 if ((fd = uv_fs_open(tc->loop, &req, filename, O_RDONLY, 0, NULL)) < 0) {
253 51 MVM_exception_throw_adhoc(tc, "While trying to open '%s': %s", filename, uv_strerror(req.result));
254 52 }
255 53
256 54 if ((block = MVM_platform_map_file(fd, &handle, (size_t)size, 0)) == NULL) {
257 55 /* FIXME: check errno or GetLastError() */
258 56 MVM_exception_throw_adhoc(tc, "Could not map file '%s' into memory: %s", filename, "FIXME");
259 57 }
260 58
261 59 if (uv_fs_close(tc->loop, &req, fd, NULL) < 0) {
262 (lldb)
263 60 MVM_exception_throw_adhoc(tc, "Failed to close filehandle: %s", uv_strerror(req.result));
264 61 }
265 62
266 63 /* Turn it into a compilation unit. */
267 64 cu = MVM_cu_from_bytes(tc, (MVMuint8 *)block, (MVMuint32)size);
268 65 cu->body.handle = handle;
269 66 cu->body.deallocate = MVM_DEALLOCATE_UNMAP;
270 67 return cu;
271 68 }
272 ```
273
274 * 54行目
275
276 # 生成箇所?
277
278 ```
279 63 void *MVM_platform_map_file(int fd, void **handle, size_t size, int writable)
280 64 {
281 65 void *block = mmap(NULL, size,
282 66 writable ? PROT_READ | PROT_WRITE : PROT_READ,
283 67 writable ? MAP_SHARED : MAP_PRIVATE, fd, 0);
284 68
285 (lldb)
286 69 (void)handle;
287 70 return block != MAP_FAILED ? block : NULL;
288 71 }
289 ```
290
291 # 実際に作成している箇所
292
293 ```
294 (lldb) l 10
295 10 MVMCompUnit * MVM_cu_from_bytes(MVMThreadContext *tc, MVMuint8 *bytes, MVMuint32 size) {
296 11 /* Create compilation unit data structure. Allocate it in gen2 always, so
297 12 * it will never move (the JIT relies on this). */
298 13 MVMCompUnit *cu;
299 14 MVM_gc_allocate_gen2_default_set(tc);
300 15 cu = (MVMCompUnit *)MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTCompUnit);
301 16 cu->body.data_start = bytes;
302 17 cu->body.data_size = size;
303 18 MVM_gc_allocate_gen2_default_clear(tc);
304 ```
305
306 ```
307 16 MVMObject * MVM_repr_alloc_init(MVMThreadContext *tc, MVMObject *type) {
308 17 MVMObject *obj = REPR(type)->allocate(tc, STABLE(type));
309 18
310 19 if (REPR(obj)->initialize) {
311 20 MVMROOT(tc, obj, {
312 21 REPR(obj)->initialize(tc, STABLE(obj), obj, OBJECT_BODY(obj));
313 (lldb)
314 22 });
315 23 }
316 24
317 25 return obj;
318 26 }
319 ```