1.歴史的背景
1. Graal仮想マシンとGraalコンパイラはまだラボで市販されていませんが、将来的には次世代のHotSpotテクノロジーに取って代わるか、その基盤になることが期待されています。Graalコンパイラは元々Maxine仮想マシン[illustration]でC1Xコンパイラ[illustration]の次世代コンパイラとして設計されていたので、もちろんJava言語で書かれています。
2. 2012年、GraalコンパイラはMaxine仮想マシンプロジェクトから分離され、独自に開発されたJavaコンパイラプロジェクトになりました。
3. Graalコンパイラは、JDK 9のJaotc事前コンパイルツールの形式で公式JDKに最初に追加されました。JDK10以降、Graalコンパイラはサーバー側コンパイラに置き換わり、HotSpotの階層化コンパイルでトップレベルのジャストインタイムコンパイルになります。端末。この代替のジャストインタイムコンパイラアーキテクチャの実現は、HotSpotコンパイラインターフェイスの出現から恩恵を受けています。
4. Graalの初期には、C1やC2と同様に、HotSpotとのコラボレーションは緊密に結合されていました。つまり、Graalをコンパイルするたびに、HotSpot全体を再コンパイルする必要がありました。JEP 243:JDK 9でリリースされたJavaレベルのJVMコンパイラインターフェイス(JVMCI)により、GraalをHotSpotのコードから分離できます。
5.JVMCIの3つの機能
A:HotSpotのコンパイル要求に応答し、Javaによって実装されたジャストインタイムコンパイラに要求を配布します。
B:コンパイラがHotSpotでのJITコンパイルに関連するデータ構造(クラス、フィールド、メソッド、パフォーマンス監視データなど)にアクセスできるようにし、これらのデータ構造の一連の抽象表現をJava言語レベルで提供します。
C:HotSpotコードキャッシュのJava側の抽象表現を提供し、コンパイラがコンパイルされたバイナリマシンコードを展開できるようにします。
3つの関数を使用すると、HotSpot仮想マシンの外部でJava言語で実装されたジャストインタイムコンパイラ(Graalに限定されない)をHotSpotに統合し、HotSpotによって発行された最上位のコンパイル要求に応答し、コンパイルされたバイナリコードを変換できます。 HotSpotのコードキャッシュにデプロイします。
6. Java仮想マシンとコンパイラの開発に直接携わっていないがJava仮想マシンテクノロジに興味がある読者のために、GraalとJVMCIの登場は、コンパイラテクノロジをスヌープして試すための良い方法を提供します。 Graalは、HotSpot仮想マシンのリアルタイムのコンパイルおよびコード最適化プロセスに使用されます。
2つ目は、コンパイルおよびデバッグ環境を構築することです。
1.コード管理、依存関係管理、コンパイル、およびテストの複雑さを軽減するために、Graalチームは、これらを自動化するためにPython2でmxと呼ばれる小さなツールを作成しました。
2.最初にmxをインストールします
# git clone https://github.com/graalvm/mx.git
# 倒入环境变量
export PATH = 'pwd'/mx:$PATH
説明
コンパイルするのに適したJDKを見つけます。GraalVMプロジェクトはOpenJDK8に基づいて開発され、JVMCIインターフェイスはJDK 9の後に提供されることを考慮して、GraalチームはJVMCI機能を備えたOpenJDK8バージョンを提供しました。このバージョンのJDK8を選択してコンパイルできます。 。読者がHotSpotでのGraalコンパイラのアプリケーションにのみ注意を払い、Graal VMの他の側面を関与させたくない場合は、JDK9以降の標準Open / OracleJDKを直接使用できます。
IDEでのGraalのコンパイルと構築をスムーズに進めるには、IDE構成で使用されるJavaヒープを2GB以上に変更する必要があります。
3.Javaバージョンに対応する環境変数を構成します
export JAVA_HOME=/usr/lib/jvm/oraclejdk1.8.0...
4、Graalコンパイラコードを取得することです
# git clone https://github.com/graalvm/graal.git
# cd /graal/comiler
# mx build
3、JVMCIコンパイラインターフェイス
1.JVMCIインターフェースのコアコンテンツは実際には
バイトコード、変数テーブル内の可変スロットの数、オペランドスタックの最大深度、および階層化されたコンパイルの下部で収集された統計情報。
2.インターフェース
interface JVMCICompiler {
}
interface CompliationRequest {
}
interface JavaMethod {
}
第四に、コード中間表現
1.コードはコンパイラ内にあります
バイトコード→理想的なグラフ→最適化→マシンコード(マッハノードグラフで表される)の変換プロセス。
2.理想的なグラフは有向グラフです。ノードは変数、演算子、メソッド、フィールドなどのプログラム内の要素を表すために使用され、エッジはデータまたは制御フローを表すために使用されます。
A:作成者は、データフローに青い線(破線で示されている)を使用し、制御フローに赤い線(実線で示されている)を使用しています)
B:理想的なグラフは、基本的に、データフローグラフと制御フローグラフを特定の方法で組み合わせたグラフィック表現であり、一方の種類のエッジを使用してデータフローを表し、もう一方の種類のエッジを使用して制御フローを表します。
パラメータ0(P(0)と表記)とパラメータ1(P(1)と表記)を加算演算に送信する方法と、結果を定数2(C(2)と表記)とともに除算演算に送信する方法。
3.一般的な単語表現の排除
5、コードの最適化と生成
1.理想的なグラフの各ノードには、共通の2つの主要な操作があります。1つは正規化であり、もう1つは生成です。
2.標準化とは、理想的なグラフのスケールを縮小する方法、つまり、理想的なグラフに基づいてコードを最適化するために実行する手段を指します。
3.グラフで削除できる算術部分式を見つけたい場合は、重複ノードを見つけて、それを置き換えるか削除します。
例:
2つの整数を追加するという単純な操作では、定数フォールディング(両方のオペランドが定数の場合、定数ノードが直接返される)、算術集計((a +などの集計ツリーの定数子ノード)も試行されました。 1)+2がa + 3)に集約され、符号マージ(たとえば、集約ツリーの反対の符号サブノードが(ab)+ bまたはb +(ab)をaに直接マージ)および他の多くの最適化。
4. Graalは、理想的なグラフからマシンコードに直接変換されませんが、他のコンパイラと同様に、最初に低レベルの中間表現(LIR、特定のマシン命令セットに関連する中間表現)を生成し、次にHotSpot統合バックエンドを生成します。マシンコードを生成します。
算術加算を含む操作の場合、ArithmeticLIRGeneratorToolインターフェイスのemitAdd()メソッドで実行されます。
5.Graalコンパイラでサポートされているターゲットプラットフォーム
現在、3つのターゲットプラットフォーム(SPARC、x86-AMD64、ARMv8-AArch64)の命令セットの低レベルの中間表現のみを提供します。
6.正規化は、単一のopcodeのローカルスコープに限定されません。多くの最適化は、全体的な状況に基づいています。このタイプの操作は、CanonicalizerPhaseクラスで完了します。