Javascript Engine (V8, SpiderMonkey, JerryScript, Duktape) で遊ぶ

色々な Javascript Engine で遊んでみた。意外とエンジンごとに特徴があった。

## 比較

| Javascript Engine | ビルド時間(かなり良い Ubuntu 16.04) | 実行ファイルの大きさ | シェル起動後のメモリサイズ (VmHWM) | 感想 |
|-----|-----|-----|-----|-----|
| V8 (Google) | 61 分 |  17M | 13040 kB | ビルドが面倒くさい |
| SpiderMonkey (Mozilla) | 12 分 | 209M | 16804 kB | バイナリサイズが大きい |
| JerryScript (Samsung) | 5 秒 | 218K | 4kB | Javascript が古いがメモリが少ない |
| Duktape | 4 秒 | 308K | 1088kB | 楽 |

## V8

Getting Started: https://github.com/v8/v8/wiki/Getting%20Started%20with%20Embedding

に書いてある事をなぞってみる。V8 は depot_tools とか言う特殊なツールでダウンロードやビルドを行うので、ちょっとややこしい。

### ソースコードのダウンロード

depot_tools のダウンロードと PATH 設定

    $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
    $ export PATH=`pwd`/depot_tools:"$PATH"

Google Source にログイン。[Configure Git](https://chromium.googlesource.com/new-password) に行って適当なアカウントでログインし、コマンド文字列をシェルにコピペする。

以下のコマンドでインストールが上手く行ったか確認。

    $ gclient

v8 のダウンロード (2 - 3 分)

    $ fetch v8
    $ cd v8

サンプルのバージョンに合せる

    $ git checkout -b 5.8 -t branch-heads/5.8

ビルド設定

    $ tools/dev/v8gen.py x64.release

ビルド設定を編集するために以下実行

    $ gn args out.gn/x64.release

エディタが起動するので、以下修正追加

    is_component_build = false
    v8_static_library = true

### ビルド (一時間)

    $ ninja -C out.gn/x64.release

### テスト

samples/hello-world.cc にサンプルがあるのでビルド。同様に samples/shell をビルドすると REPL が出来る。

    $ g++ -I. -Iinclude samples/hello-world.cc -o hello-world -Wl,--start-group \
    out.gn/x64.release/obj/{libv8_{base,libbase,external_snapshot,libplatform,libsampler},\
    third_party/icu/libicu{uc,i18n},src/inspector/libinspector}.a \
    -Wl,--end-group -lrt -ldl -pthread -std=c++0x

スナップショットファイル (natives_blob.bin, snapshot_blob.bin) と ICU ファイル (icudtl.dat) を実行ファイルの場所にコピー

    $ cp out.gn/x64.release/*.bin .
    $ cp out.gn/x64.release/icudtl.dat .

サンプルプログラムを実行

    $ ./hello-world 
    Hello, World!

### 特徴

* 実行サイズの大きさ: 17M
* shell 起動直後のメモリサイズ: VmHWM: 13040 kB

### 宿題

* bin ファイル、ICU ファイルとは何か?
* hello-world.cc の中身を変える。
* v8 に機能を追加する。

## SpiderMonkey

https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Build_Documentation を元に作業

### 依存ツールインストールとソースコードのダウンロード

    sudo apt install -y autoconf2.13
    git clone --depth 1 https://github.com/mozilla/gecko-dev.git
    cd gecko-dev/js/src

### ビルド (12 分)

    autoconf2.13 
    mkdir build_OPT.OBJ
    cd build_OPT.OBJ
    ../configure
    make

### 起動

    $ ./js/src/shell/js
    js> print("hello world!")
    hello world!

### 特徴

* 実行ファイルの大きさ: 209M
* js 起動直後のメモリサイズ: VmHWM: 16804 kB

## JerryScript

### ダウンロード

    git clone https://github.com/jerryscript-project/jerryscript.git
    cd jerryscript

### ビルド (5秒)

    python tools/build.py 

### 実行

    ./build/bin/jerry 

### 特徴

* 実行ファイルの大きさ: 218K
* シェル起動直後のメモリサイズ: 4kB

## Duktape

### ダウンロード

    $ wget http://duktape.org/duktape-2.1.0.tar.xz
    $ tar xJvf duktape-2.1.0.tar.xz
    $ cd duktape-2.1.0

### ビルド (4秒)

    $ make -f Makefile.cmdline

### 実行

    $ ./duk

### 特徴

* 実行ファイルの大きさ: 308K
* シェル直後のメモリサイズ: 1088 kB 

## おまけ。Javascript の機能がどの仕様で定義されているか?

Javascript では。最初から幾つかの関数やオブジェクトが使える。それらの機能がどの仕様で定義されているのか調べてみた。

* ECMAScript で定義されている機能
    * [18 The Global Object](https://www.ecma-international.org/ecma-262/7.0/index.html#sec-global-object) で Ecmascript のグローバルオブジェクトが定義されている。
    * decodeURI などの歴史的関数
    * Array, Set などの基本オブジェクト
    * JSON, Math などのユーティリティ
    * V8 では https://github.com/v8/v8/blob/master/src/bootstrapper.cc#L4191 あたりで登録している。
* WHATWG で定義されている機能
    * 非常にわかりにくいが https://spec.whatwg.org/ から辿れるページに分割されて書かれている。
    * [7.3 The Window object](https://html.spec.whatwg.org/#the-window-object)
        * window, history, navigator 等のブラウザ操作関数
    * [8 Web application APIs](https://html.spec.whatwg.org/multipage/webappapis.html) 特に [8.2 The WindowOrWorkerGlobalScope mixin](https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin)
        * btoa などの歴史的関数
        * setTimeout などのタイマ
        * createImageBitmap などの置き場所に困った雰囲気の関数。
    * Notifications, Console, XMLHttpRequest などは独立した文書になっている。
* node.js が定義している機能
    * https://nodejs.org/api/ にわかりやすく定義されている。

## 他の javascript エンジン

* ChakraCore (Microsoft) https://github.com/Microsoft/ChakraCore