LoginSignup
6
6

More than 5 years have passed since last update.

Jasmin形式のパースとclassファイルの生成

Posted at

この記事は言語処理系 Advent Calender3日目の記事です。

1日目がJVMバイトコードの記事でしたので、今日はJasmin形式からclassファイルを作成する段階のお話をしようと思います。
jasc[1]はOCamlで作成したJVMバイトコードアセンブラです。Jasmin[2]とコンパチブルな機能を持ちます。全てのJasminの機能を持っているわけではありませんが、joose0コンパイラのバックエンドとして動作するレベルの機能を有しています。joose言語(JVM言語のコンパイラ)とペアで必要な機能を追加して行くと良いだろうと考えていました。jascはHaxe[3]のjavalib[4]を参考にしています。言い換えればjascはHaxeのJavalibにバイトコード操作を加え、Jasminのフロントエンドを加えた物です。

モチベーション

Scalaのコンパイルが遅いのでOCamlで再実装したら良いだろうとの思いで作り始めました。
コンパイラを作成するには、まずバイトコードの操作が出来ないといけません。

OPAMのJavalib[5]は、バイトコードが扱える拡張がされていました。しかし、高レベル表現を持ち、いくつかバグがあり、またWindowsでOPAMが動かなかったのでコンパイル出来ませんでした。Javalibの元を辿るとHaxeの作者の Nicolas Cannasse により作成されていました。HaxeにもJavalibがあります。extlibもHaxeの作者が関わっていたようです。HaxeコンパイラはWindowsで動作させる為にextlibやjavalibを内蔵しています。そこでjascもextlibも内蔵することにしました。

jascはOPAMのJavalibの高レベル表現をなくしてスリムにしたものに、Jasminのフロントエンドを加えた、あるいはHaxeのJavaLibにバイトコード操作機能とJasminのフロントエンドを加えた物です。

ライセンス

LGPLです。
理由はjavalibやextライブラリがLGPLだからです。
これは自由に使えたほうがよいと考えているのでMITライセンスにしたいところです。

性能

OCamlのバイトコードでもネイティブでも高速に起動します。
extlibは内部では破壊的な操作も行うなどして高速化されています。
OPAM上のJavaLibは高レベルインターフェイスを持っていて多段階のパスがありましたがjascでは高レベルインターフェイスを無くす事で高速化を図りました。
構文解析は伝統的なocamllex, ocamlyaccを用いており高速です。

ただし性能は測定していません。<ちゃんと測りましょう。

ジャンプ動作の関係で配列に値を保存していますが、これは他のデータ構造にしたほうが速くなる事はあるかもしれません。文字列を生成するよりも直接バイトコードを操作したほうが高速でしょうが、やはり測定してみないと分かりません。

構成

JCodeモジュールがバイトコードを表し、JDataモジュールがクラスファイルを表します。

  • ext 便利で高速なライブラリです。
    • ext/IO.ml IO周りの便利なライブラリです。
    • ext/enum.ml extlibの基本アルゴリズムが含まれています。iterとかfoldとかです。
    • ext/extList.ml リスト周りの便利で高速なライブラリです。
    • ext/extString.ml 文字列周りの便利で高速なライブラリです。
    • ext/pMap.ml 便利で高速なMapです。
  • jCode.ml バイトコードを表します。
    • jCodeReader.ml バイトコードの読み込みを行います。
    • jCodeWriter.ml バイトコードの書き出しを行います。
    • jCodePP.ml バイトコードのプリティプリントを行います。
  • jData.ml クラスファイルを表します。
    • jReader.ml クラスファイルの読み込みを行います。
    • jWriter.ml クラスファイルの書き出しを行います。
    • jDataPP.ml クラスファイルのプリティプリントを行います。
  • parser.mly Jasminの構文解析器です。
  • lexer.mll Jasminの字句解析器です。
  • jasc.ml メインルーチンです。
$ wc *.ml*
     134     610    3310 jCode.ml
     203    1311   11216 jCodePP.ml
     214    1432    7822 jCodeReader.ml
     269    1583    9175 jCodeWriter.ml
     174     988    5469 jData.ml
     322    1628   13818 jDataPP.ml
     655    3313   20561 jReader.ml
     569    2377   18794 jWriter.ml
      67     246    1671 jasc.ml
     379    2390   19584 lexer.mll
    1440    6297   50643 parser.mly
    4426   22175  162063 total

extlibは省くと、4426行で、パーサが大きいです。
parserとlexerを省くと、2607行です。parserはまだまだ発展途上です。

ちなみにextlibは2114行です。

$ wc ext/*.ml
     796    3231   17062 ext/IO.ml
     376    1358    7018 ext/enum.ml
     508    2307   10204 ext/extList.ml
     237    1037    5024 ext/extString.ml
     197    1174    5391 ext/pMap.ml
    2114    9107   44699 total

アドレスから見ても分かる通りあまり本気ではないはずだったのですが、結構大きなプロジェクトになって来ていますね。これように、リポジトリ分けるか。

今後

MinCamlのJVM実装からjascを呼び出せば、より高速に動作させる事が出来るかもしれません(必要な機能がなければ作ればいいのです)。また、直接ライブラリを呼べば高速に出来るでしょう。ライブラリのインターフェイスが不満なら、OPAMのJavalibの挑戦のように、より洗練されたインターフェイスを作る事に繋がるでしょう。

参考文献

6
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6