nova_vmのバイトコード処理のコードリーディング
最近Novaで実装したい機能のためにbytecode_compiler.rsとその周辺をを読んでいるのでメモがてら書く。
本当にただのメモなので、多分読んでも面白くない。
内容
そもそもバイトコードとは、高級言語のコードを仮想マシン向けに変換した中間コードのこと。NovaのVMでは、このバイトコードを解釈・実行することでJavaScriptを処理する。
今回は以下のコマンドを実行した時の動作を想定して、コードを読んでいく。
ここではコマンドの詳細は省く。
cargo run --features typescript eval index.ts
まず一番トップはnova_cliから始まる。
実行したjsファイルをparse_scriptし、そのscriptをそのまま渡している。parse_scriptの仕様はecma262に書いてあるのでまたどこかで読みたい。
そしてその関数の中で、Vm::execute
というのがよばれていて、ここでbytecodeが渡されている。
そしてそのままさらにその中でVm::internal_execute
というのが呼ばれている。
そして中を覗くと、以下のようなコードがある
よくわからないので、printlnしてみよう。以下のような出力になる
// cargo run --features typescript eval index.ts
const obj = { a: 1, b: "hello" };
// log
instructions: [83, 0, 0, 81, 72, 89, 1, 0, 65, 89, 2, 0, 73, 89, 3, 0, 65, 89, 4, 0, 73, 87, 79, 102, 89, 5, 0, 86]
大量のバイトコードらしきものが返ってきた。
次にこれをループして、数字一つ一つ、VM:execute_instruction
に渡している。
そして渡されたinstructionにはkindというプロパティがあり、matchしたものに対して処理が行われるようになっている
例えば、先ほどのjsのオブジェクトだと、以下のようなkindになっている。
instr.kind: ResolveBinding
instr.kind: PushReference
instr.kind: ObjectCreate
instr.kind: StoreConstant
instr.kind: Load
instr.kind: StoreConstant
instr.kind: ObjectDefineProperty
instr.kind: StoreConstant
instr.kind: Load
instr.kind: StoreConstant
instr.kind: ObjectDefineProperty
instr.kind: Store
instr.kind: PopReference
instr.kind: InitializeReferencedBinding
instr.kind: StoreConstant
instr.kind: Return
ObjectCreateの処理は以下のように定義されている。
そしてinstr.kind: Return
とあるように、最終的にReturnが返されると以下のように実行される。
ExecutionResult::Return
でValueをReturnしてそうな雰囲気を感じている
Discussion