FacebookのHermesというJSエンジンがエロい

FacebookがHermesという組み込みのJSエンジンを公開したようです。

* ReactNative用の組み込み用のJSエンジン（最新版だとオプション切り替えで使えるっぽい）
* MITライセンス
    * プロプラなものとの組み合わせが発生しうる組み込みにおいては正義しかない
* [ES2015をサポート(予定）](https://github.com/facebook/hermes/blob/master/doc/Features.md)
    * 現時点ではクラスとかlet/constのブロックスコープは実装途中
    * Map/Setとかの組み込みクラス系は実装済み
    * サイズの小ささをうたった処理系はES2015への対応はまだまだなのが多いので（Duktapeとか）良い
* 事前にJavaScriptのソースコードをパースして中間表現（LLVM IRをそのまま利用？）にしておいてロードする
    * モバイルのCPUやバッテリー、メモリーにも優しい

なお、エロいというのは強く感情が揺さぶられた結果が出てきたワードであってセクシャルな内容は一切含まれておりません。

コードを読む限りでは今どきっぽい感じがいろいろ伝わってきます。

* LLVMにかなり依存している感じ
    * [LLVMへのパッチ](https://github.com/facebook/hermes/blob/master/utils/llvm-changes-for-hermes.patch)とかもある
* GCは[世代別GC](https://github.com/facebook/hermes/tree/master/lib/VM/gcs)っぽい？
* [JSI](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/jsi.h)というのがJavaScriptインタプリタへのインタフェース
    * よくあるJSインタプリタのC++インタフェースで、Qtの組み込みとかV8とかを見たことがある人はたぶん、0.1秒で理解できる感じ。わかりやすい。
    * いつもの感じで、ホスト側ではインタプリタの[Value](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/jsi.h#L892)をとってきてゴニョゴニョする感じになるんだと思われる
    * [FacebookのC++ライブラリfolly](https://github.com/facebook/folly)（ノリはJREっぽい）でサポートされている動的値型の[dynamic型とのインタフェース](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/JSIDynamic.h)もある。まあこれは値型との交換でインタプリタには入り込んでないので、この関数を使わなければfollyへはリンクされない（されても除外される）かな？
* ランタイムがいくつもあってわからん
    * JSIの中にRuntimeクラスがあるが、[スレッドセーフなランタイム](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/threadsafe.h)もあれば、[ビルド済みのIRを読み込む機能がついたランタイム](https://github.com/facebook/hermes/blob/master/API/hermes/hermes.h)（これがHermesという名前）もある。[トレーシングランタイム](https://github.com/facebook/hermes/blob/master/API/hermes/TracingRuntime.h)というのもある。トレーシングランタイムはデコレータとして実装されているので、他のランタイムにアドオンできるっぽい。面白いなー
* 事前コンパイルしたものを読み込むが、[ソースコードからのコンパイラもランタイムには抱えている](https://github.com/facebook/hermes/blob/master/API/hermes/CompileJS.h)？
    * まあこれがReactNativeにバンドルされるのかはCMakefileを見たけどわからん
    * とはいえ、evalはサポートしていないし、REPL用かもしれない。
* OSへのライブラリとしてのシステムコール的な呼び出しは[現在はファイルとmmapぐらい](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/jsilib-posix.cpp)？
    * [Windowsのみんな、泣いていいよ](https://github.com/facebook/hermes/blob/master/API/jsi/jsi/jsilib-windows.cpp)
* OSへのランタイムとしてのシステムコール的な呼び出しは[メモリとスレッドとか](https://github.com/facebook/hermes/blob/master/lib/Support/OSCompatPosix.cpp)
    * スレッドは情報取得系の関数を呼んでいるだけっぽいので、内部でスレッドを立ち上げたり云々みたいなことはなさそう。
    * [Unicode](https://github.com/facebook/hermes/tree/master/lib/Platform/Unicode)は、AndroidであればJava、iOS/macOSであればCoreFoundation、そうじゃなかったらICUにフォールバックしている？でもCMakeみると、両方CoreFoundationをリンクしているように見えるしよくわからん。CMakeはいくらやっても理解できん。
* [正規表現は内部でLLVM使っている](https://github.com/facebook/hermes/blob/master/lib/Regex/Executor.cpp)ので速そう
* [オプティマイザ](https://github.com/facebook/hermes/tree/master/lib/Optimizer/Scalar)もいっぱいある
* [外部依存](https://github.com/facebook/hermes/tree/master/external)は少なめ
* ツールフォルダもなかなか面白い
    * [hermes](https://github.com/facebook/hermes/blob/master/tools/hermes/hermes.cpp)はIRにするコンパイラかな？なお、バイトコード実行とかJSからの実行ももできるっぽい。JIT有効オプションがあったりするし、プロファイラを有効にするとか、乱数の種のサニタイズ、メモリアドレスのランダム化というセキュリティ用の項目もある。中間言語処理系でもセキュリティが大事な時代。これらのオプションは実行用かな？
        * hermescというのもある。スタンドアローンコンパイラ。
    * [hvm](https://github.com/facebook/hermes/blob/master/tools/hvm/hvm.cpp)は実行用のVMかな？
    * [jsi](https://github.com/facebook/hermes/blob/master/tools/jsi/jsi.cpp)はJavaScriptをevalしてそのまま実行する組み込みライブラリなしのnode.jsとかみたいなやつっぽい。[repl](https://github.com/facebook/hermes/tree/master/tools/repl)もある
    * [hdb](https://github.com/facebook/hermes/tree/master/tools/hdb)というデバッガもある
    * hbc-で始まるやつらはhemesのbytecode用のユーティリティ。[hbc-diff](https://github.com/facebook/hermes/tree/master/tools/hbc-diff)というdiff生成するツールもある
    * [fuzzer](https://github.com/facebook/hermes/blob/master/tools/fuzzer/fuzzer.cpp)ってのはファジングのテストなのかな？

これを例えばGoとかに組み込むのであれば、toolsのhvmあたりを参考にすれば良さそう。

用途としては、例えばGoでもDukTapeを使ってサーバーサイドレンダリングしよう、みたいな流れもあったりするので、そういうところでは使えそうですね。

なお、言語的にはclassとかlet/constがまだ実装中以外に、es2015 modulesも実装中というのがあります。動的ロードのimport()とかもサポートにはなっていない。そのかわりに[require](https://github.com/facebook/hermes/blob/master/doc/Modules.md)をサポートしていたり、モジュール構成の設定ファイルがあったりする。このあたりがwebpackとかで生成できると良いのかな。プロジェクトを作るときの要注意ポイントな気もするし、シングルバイナリにしてしまうならいらないのかもしれない。isomorphicなJSプロジェクトを作る場合に、コードをチャンクに分けてロード時間の最適化、というのをやろうとするとひと手間余計にHermes用の作業が発生しますね、確実に。