Mercurial > hg > Members > anatofuz > slides
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 ``` |