📝

nova_vmのバイトコード処理のコードリーディング

に公開

最近Novaで実装したい機能のためにbytecode_compiler.rsとその周辺をを読んでいるのでメモがてら書く。

本当にただのメモなので、多分読んでも面白くない。

内容

そもそもバイトコードとは、高級言語のコードを仮想マシン向けに変換した中間コードのこと。NovaのVMでは、このバイトコードを解釈・実行することでJavaScriptを処理する。

今回は以下のコマンドを実行した時の動作を想定して、コードを読んでいく。
ここではコマンドの詳細は省く。

cargo run --features typescript eval index.ts

まず一番トップはnova_cliから始まる。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_cli/src/main.rs#L196

実行したjsファイルをparse_scriptし、そのscriptをそのまま渡している。parse_scriptの仕様はecma262に書いてあるのでまたどこかで読みたい。

そしてその関数の中で、Vm::executeというのがよばれていて、ここでbytecodeが渡されている。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/ecmascript/scripts_and_modules/script.rs#L310

そしてそのままさらにその中でVm::internal_executeというのが呼ばれている。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L299

そして中を覗くと、以下のようなコードがある
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L339-L340

よくわからないので、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に渡している。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L360

そして渡されたinstructionにはkindというプロパティがあり、matchしたものに対して処理が行われるようになっている
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L418

例えば、先ほどの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の処理は以下のように定義されている。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L983-L991

そしてinstr.kind: Returnとあるように、最終的にReturnが返されると以下のように実行される。
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L361-L384

ExecutionResult::ReturnでValueをReturnしてそうな雰囲気を感じている
https://github.com/trynova/nova/blob/08ac2abeef4bf20241b3ff31d5fed28423d0d153/nova_vm/src/engine/bytecode/vm.rs#L110

Discussion