2018-05-14---- 今日の進捗 # MoarVMのJIT * [Docs](https://github.com/MoarVM/MoarVM/tree/master/docs)を見る # Lego * MoarMVのJITはLegoと呼ばれているらしい # DynASM * Dynamic Assemler * http://luajit.org/dynasm.html * [luajit](http://luajit.org/)プロジェクトで作られているもの * MoarVMには `3rdparty`ディレクトリ以下に展開されている * x86アーキテクチャのJITコンパイル用のアセンブラのようなものらしい * luaが`dasc`と呼ばれるCに近いアセンブラをCを出力する前に実行 * Cのヘッダーの `#include` している部分を機械語にランタイムで翻訳 * [GitHubのcommit](https://github.com/MoarVM/MoarVM/commit/372d0582ab90d4ddfc43553bbebe4e553a42278d) # DynASM - To get you started, here is a simple code snippet to be pre-processed. The lines starting with '|' (the pipe symbol) are for DynASM: ``` if (ptr != NULL) { | mov eax, foo+17 | mov edx, [eax+esi*2+0x20] | add ebx, [ecx+bar(ptr, 9)] } ``` - After pre-processing you get: ``` if (ptr != NULL) { dasm_put(Dst, 123, foo+17, bar(ptr, 9)); } ``` ---------- 2018-05-15---- # ゼミ - 論文自体は昔のもの - MoarVMどこが遅いのか? JITがアレ? - 直接バイナリを吐かない理由は? - Comon Lisp Cに変換して生成したオブジェクトを作る - その他の最適化はCコンパイラに投げる - 京都で開発された 京都CommonLisp - Lisp中でread evalループを持っていた - interpretするルーチンがLISPで書かれている - -->普段はCコンパイラが呼ばれない - stack をlistの管理で行う - JITが遅いならCbCの入る場所がなさそう - 直接アセンブラを書いても良さそう - MoarVMからCbCを吐く - 帯域脱出が問題 - スタックの管理ならCbCでいけるかもしれない - MoarVMの - 行き先を渡す - 厳しいなら構造体にいれてあげる - diコンテナ - 見かけ上関数呼び出しっぽく書ける - Cの再実装 - 比較して見る - 頻度の高いif文を先に持っていって再構築 - CbC側を書き換えるのをどうするか ---------- 2018-05-16---- MVMSpeshFactsが主に使われている構造体 宣言元はfacts.h ```c struct MVMSpeshFacts { /* Flags indicating things we know. */ MVMint32 flags; /* The number of usages it has. */ MVMint32 usages; /* Known type, if any. */ MVMObject *type; /* Known type post-decontainerization, if any. */ MVMObject *decont_type; /* Known value, if any. */ union { MVMObject *o; MVMint64 i; MVMnum64 n; MVMString *s; } value; /* The instruction that writes the register (noting we're in SSA form, so * this is unique). */ MVMSpeshIns *writer; /* The deoptimization index in effect at the point of declaration, or -1 * if none yet. */ MVMint32 deopt_idx; /* The log guard the facts depend on, if any. */ MVMuint32 log_guard; /* Has the instruction that wrote this value been deleted? */ MVMuint32 dead_writer; }; ``` fact のflag一覧 ```c /* Various fact flags. */ #define MVM_SPESH_FACT_KNOWN_TYPE 1 /* Has a known type. */ #define MVM_SPESH_FACT_KNOWN_VALUE 2 /* Has a known value. */ #define MVM_SPESH_FACT_DECONTED 4 /* Know it's decontainerized. */ #define MVM_SPESH_FACT_CONCRETE 8 /* Know it's a concrete object. */ #define MVM_SPESH_FACT_TYPEOBJ 16 /* Know it's a type object. */ #define MVM_SPESH_FACT_KNOWN_DECONT_TYPE 32 /* Has a known type after decont. */ #define MVM_SPESH_FACT_DECONT_CONCRETE 64 /* Is concrete after decont. */ #define MVM_SPESH_FACT_DECONT_TYPEOBJ 128 /* Is a type object after decont. */ #define MVM_SPESH_FACT_FROM_LOG_GUARD 256 /* Depends on a guard being met. */ #define MVM_SPESH_FACT_HASH_ITER 512 /* Is an iter over hashes. */ #define MVM_SPESH_FACT_ARRAY_ITER 1024 /* Is an iter over arrays (mutually exclusive with HASH_ITER, but neither of them is nece ssarily set) */ #define MVM_SPESH_FACT_KNOWN_BOX_SRC 2048 /* We know what register this value was boxed from */ #define MVM_SPESH_FACT_MERGED_WITH_LOG_GUARD 4096 /* These facts were merged at a PHI node, but at least one of the incoming facts had a "from log guard" flag set, so we'll have to look for that fact and increment its uses if we u se this here fact. */ #define MVM_SPESH_FACT_RW_CONT 8192 /* Known to be an rw container */ void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p); void MVM_spesh_facts_depend(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshFacts *target, MVMSpeshFacts *source); ``` `spesh/graph.h`の箇所 ``` /* An instruction in the spesh graph. */ struct MVMSpeshIns { /* Instruction information. */ const MVMOpInfo *info; /* Operand information. */ MVMSpeshOperand *operands; /* Previous and next instructions, within a basic block boundary. */ MVMSpeshIns *prev; MVMSpeshIns *next; /* Any annotations on the instruction. */ MVMSpeshAnn *annotations; }; ``` `core/interp.h` ``` /* Information about an opcode. */ struct MVMOpInfo { MVMuint16 opcode; const char *name; char mark[2]; MVMuint16 num_operands; MVMuint8 pure; MVMuint8 deopt_point; MVMuint8 logged; MVMuint8 no_inline; MVMuint8 jittivity; MVMuint8 uses_hll; MVMuint8 operands[MVM_MAX_OPERANDS]; }; ``` ---------- 2018-05-18---- moar.h l.41あたり ```c /* Sized types. */ typedef int8_t MVMint8; typedef uint8_t MVMuint8; typedef int16_t MVMint16; typedef uint16_t MVMuint16; typedef int32_t MVMint32; typedef uint32_t MVMuint32; typedef int64_t MVMint64; typedef uint64_t MVMuint64; typedef float MVMnum32; typedef double MVMnum64; ``` ただのtypes のSizedのフラグ src/core/ops.h でdefineされている ただの変数 ``` /* This file is generated from src/core/oplist by tools/update_ops.p6. */ /* Op name defines. */ #define MVM_OP_no_op 0 #define MVM_OP_const_i8 1 #define MVM_OP_const_i16 2 #define MVM_OP_const_i32 3 #define MVM_OP_const_i64 4 #define MVM_OP_const_n32 5 #define MVM_OP_const_n64 6 #define MVM_OP_const_s 7 #define MVM_OP_set 8 #define MVM_OP_extend_u8 9 #define MVM_OP_extend_u16 10 #define MVM_OP_extend_u32 11 #define MVM_OP_extend_i8 12 #define MVM_OP_extend_i16 13 #define MVM_OP_extend_i32 14 #define MVM_OP_trunc_u8 15 #define MVM_OP_trunc_u16 16 ``` ----------