(57)【要約】【課題】従来の方法で実行時確定メソッドをコンパイルすると、異なるクラス間でメソッドアドレス格納テーブルが冗長に生成されてしまう。【解決手段】中間コードからメソッドアドレス格納テーブル情報と、クラス情報と、関数参照情報とを抽出して解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライドしていない場合に、それぞれのクラスのメソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新することで、異なるクラス間で冗長に生成されるメソッドアドレス格納テーブルを削除し、オブジェクトコードサイズを削減することができる。【選択図】図１
2006163686.tif 000002
【特許請求の範囲】
【請求項１】
オブジェクト指向言語で記述されたソースプログラムをオブジェクトコードに変換するコンパイル方法であって、
前記ソースプログラムから中間コードを生成する中間コード生成ステップと、
前記中間コードから少なくともメソッドアドレス格納テーブル、前記メソッドアドレス格納テーブルを指しているメソッドアドレス格納テーブルポインタ、前記メソッドアドレス格納テーブルに対応するメソッドインデックス番号を含むメソッドアドレス格納テーブル情報と、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドメソッド名を含むクラス情報と、各メソッドがプログラム内で参照されているかどうかを示す関数参照情報とを抽出する解析対象情報抽出ステップと、
抽出した解析対象情報を解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライドしていない場合に、それぞれのクラスの前記メソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した前記両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新することにより前記中間コードを最適化するメソッドアドレス格納テーブル最適化ステップと、
最適化された前記中間コードをオブジェクトコードに変換するオブジェクトコード変換ステップとを含むことを特徴とするコンパイル方法。
【請求項２】
前記解析対象情報抽出ステップは、少なくともファイル名、または関数名、またはクラス名を含む解析範囲限定情報がコンパイラに与えられた場合に、指定された解析範囲に限定して前記メソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出する請求項１に記載のコンパイル方法。
【請求項３】
前記解析対象情報抽出ステップは、定義はされているものの参照はされていない実行時確定メソッドが存在する場合に、定義はされているものの参照はされていないすべての実行時確定メソッドを、クラス情報から削除し、かつすべてのメソッドアドレス格納テーブルより削除し、さらに削除後のメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス番号を更新する請求項１または請求項２に記載のコンパイル方法。
【請求項４】
前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも１つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合に、前記基底クラスのメソッドアドレス格納テーブルを削除し、さらに前記基底クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１から請求項３までのいずれかに記載のコンパイル方法。
【請求項５】
前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義していない場合に、新規に実行時確定メソッドを定義していない派生クラスのメソッドアドレス格納テーブルを削除し、さらにその派生クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない他方の派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１から請求項３までのいずれかに記載のコンパイル方法。
【請求項６】
前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義している場合で、かつ両方の派生クラスがさらに派生クラスを持たない場合に、派生クラスを持たない一方の派生クラスのメソッドアドレス格納テーブルに、他方の派生クラスで新規に定義した実行時確定メソッドのアドレスを追加したメソッドアドレス格納テーブルを新たに生成し、さらに両方の派生クラスのメソッドアドレス格納テーブルを削除し、さらに両方のメソッドアドレス格納テーブルポインタを、新たに生成したメソッドアドレス格納テーブルの先頭アドレス値に更新し、さらに新たに生成されたメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス値を更新することにより、前記中間コードを最適化する請求項１から請求項３までのいずれかに記載のコンパイル方法。
【請求項７】
前記メソッドアドレス格納テーブル最適化ステップは、各クラスのメソッドアドレス格納テーブルを比較し、一方のメソッドアドレス格納テーブルに格納されているメソッドアドレス値が、他方のメソッドアドレス格納テーブルの先頭位置に包含されている場合に、包含されている側のメソッドアドレス格納テーブルを削除し、包含されているメソッドアドレス格納テーブルを指していたクラスのメソッドアドレス格納テーブルポインタを、包含している側のメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１から請求項３までのいずれかに記載のコンパイル方法。
【請求項８】
前記メソッドアドレス格納テーブル最適化ステップは、最適化実施内容を表示させる指令がコンパイラに与えられた場合に、少なくとも最適化の対象となった前記メソッドアドレス格納テーブルを参照していたクラス、最適化前の前記メソッドアドレス格納テーブル、最適化後の前記メソッドアドレス格納テーブルを標準出力に出力する請求項１から請求項７までのいずれかに記載のコンパイル方法。
【請求項９】
前記オブジェクト指向言語をＣ＋＋言語、前記実行時確定メソッドを仮想関数、前記メソッドアドレス格納テーブルを仮想関数テーブル、前記メソッドアドレス格納テーブルポインタを仮想関数テーブルポインタとする請求項１から請求項８までのいずれかに記載のコンパイル方法。
【請求項１０】
オブジェクト指向言語で記述されたソースプログラムをオブジェクトコードに変換するコンパイルプログラムであって、
前記ソースプログラムから中間コードを生成する中間コード生成機能と、
前記中間コードから少なくともメソッドアドレス格納テーブル、前記メソッドアドレス格納テーブルを指しているメソッドアドレス格納テーブルポインタ、前記メソッドアドレス格納テーブルに対応するメソッドインデックス番号を含むメソッドアドレス格納テーブル情報と、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドメソッド名を含むクラス情報と、各メソッドがプログラム内で参照されているかどうかを示す関数参照情報とを抽出する解析対象情報抽出機能と、
抽出した解析対象情報を解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライドしていない場合に、それぞれのクラスの前記メソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した前記両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新することにより前記中間コードを最適化するメソッドアドレス格納テーブル最適化機能と、
最適化された前記中間コードをオブジェクトコードに変換するオブジェクトコード変換機能とを含むことを特徴とするコンピュータ実行可能なコンパイルプログラム。
【請求項１１】
前記解析対象情報抽出機能は、少なくともファイル名、または関数名、またはクラス名を含む解析範囲限定情報がコンパイラに与えられた場合に、指定された解析範囲に限定して前記メソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出する請求項１０に記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１２】
前記解析対象情報抽出機能は、定義はされているものの参照はされていない実行時確定メソッドが存在する場合に、定義はされているものの参照はされていないすべての実行時確定メソッドを、クラス情報から削除し、かつすべてのメソッドアドレス格納テーブルより削除し、さらに削除後のメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス番号を更新する請求項１０または請求項１１に記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１３】
前記メソッドアドレス格納テーブル最適化機能は、基底クラスに対して、少なくとも１つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合に、前記基底クラスのメソッドアドレス格納テーブルを削除し、さらに前記基底クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１０から請求項１２までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１４】
前記メソッドアドレス格納テーブル最適化機能は、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義していない場合に、新規に実行時確定メソッドを定義していない派生クラスのメソッドアドレス格納テーブルを削除し、さらにその派生クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない他方の派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１０から請求項１２までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１５】
前記メソッドアドレス格納テーブル最適化機能は、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義している場合で、かつ両方の派生クラスがさらに派生クラスを持たない場合に、派生クラスを持たない一方の派生クラスのメソッドアドレス格納テーブルに、他方の派生クラスで新規に定義した実行時確定メソッドのアドレスを追加したメソッドアドレス格納テーブルを新たに生成し、さらに両方の派生クラスのメソッドアドレス格納テーブルを削除し、さらに両方のメソッドアドレス格納テーブルポインタを、新たに生成したメソッドアドレス格納テーブルの先頭アドレス値に更新し、さらに新たに生成されたメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス値を更新することにより、前記中間コードを最適化する請求項１０から請求項１２までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１６】
前記メソッドアドレス格納テーブル最適化機能は、各クラスのメソッドアドレス格納テーブルを比較し、一方のメソッドアドレス格納テーブルに格納されているメソッドアドレス値が、他方のメソッドアドレス格納テーブルの先頭位置に包含されている場合に、包含されている側のメソッドアドレス格納テーブルを削除し、包含されているメソッドアドレス格納テーブルを指していたクラスのメソッドアドレス格納テーブルポインタを、包含している側のメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１０から請求項１２までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１７】
前記メソッドアドレス格納テーブル最適化機能は、最適化実施内容を表示させる指令がコンパイラに与えられた場合に、少なくとも最適化の対象となった前記メソッドアドレス格納テーブルを参照していたクラス、最適化前の前記メソッドアドレス格納テーブル、最適化後の前記メソッドアドレス格納テーブルを標準出力に出力する請求項１０から請求項１６までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１８】
前記オブジェクト指向言語をＣ＋＋言語、前記実行時確定メソッドを仮想関数、前記メソッドアドレス格納テーブルを仮想関数テーブル、前記メソッドアドレス格納テーブルポインタを仮想関数テーブルポインタとする請求項１０から請求項１７までのいずれかに記載のコンピュータ実行可能なコンパイルプログラム。
【請求項１９】
オブジェクト指向言語で記述されたソースプログラムをオブジェクトコードに変換するコンパイル装置であって、
前記ソースプログラムから中間コードを生成する中間コード生成手段と、
前記中間コードから少なくともメソッドアドレス格納テーブル、前記メソッドアドレス格納テーブルを指しているメソッドアドレス格納テーブルポインタ、前記メソッドアドレス格納テーブルに対応するメソッドインデックス番号を含むメソッドアドレス格納テーブル情報と、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドメソッド名を含むクラス情報と、各メソッドがプログラム内で参照されているかどうかを示す関数参照情報とを抽出する解析対象情報抽出手段と、
抽出した解析対象情報を解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライドしていない場合に、それぞれのクラスの前記メソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した前記両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新することにより前記中間コードを最適化するメソッドアドレス格納テーブル最適化手段と、
最適化された前記中間コードをオブジェクトコードに変換するオブジェクトコード変換手段とを備えたコンパイル装置。
【請求項２０】
前記解析対象情報抽出手段は、少なくともファイル名、または関数名、またはクラス名を含む解析範囲限定情報がコンパイラに与えられた場合に、指定された解析範囲に限定して前記メソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出する請求項１９に記載のコンパイル装置。
【請求項２１】
前記解析対象情報抽出手段は、定義はされているものの参照はされていない実行時確定メソッドが存在する場合に、定義はされているものの参照はされていないすべての実行時確定メソッドを、クラス情報から削除し、かつすべてのメソッドアドレス格納テーブルより削除し、さらに削除後のメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス番号を更新する請求項１９または請求項２０に記載のコンパイル装置。
【請求項２２】
前記メソッドアドレス格納テーブル最適化手段は、基底クラスに対して、少なくとも１つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合に、前記基底クラスのメソッドアドレス格納テーブルを削除し、さらに前記基底クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１９から請求項２１までのいずれかに記載のコンパイル装置。
【請求項２３】
前記メソッドアドレス格納テーブル最適化手段は、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義していない場合に、新規に実行時確定メソッドを定義していない派生クラスのメソッドアドレス格納テーブルを削除し、さらにその派生クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない他方の派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１９から請求項２１までのいずれかに記載のコンパイル装置。
【請求項２４】
前記メソッドアドレス格納テーブル最適化手段は、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義している場合で、かつ両方の派生クラスがさらに派生クラスを持たない場合に、派生クラスを持たない一方の派生クラスのメソッドアドレス格納テーブルに、他方の派生クラスで新規に定義した実行時確定メソッドのアドレスを追加したメソッドアドレス格納テーブルを新たに生成し、さらに両方の派生クラスのメソッドアドレス格納テーブルを削除し、さらに両方のメソッドアドレス格納テーブルポインタを、新たに生成したメソッドアドレス格納テーブルの先頭アドレス値に更新し、さらに新たに生成されたメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス値を更新することにより、前記中間コードを最適化する請求項１９から請求項２１までのいずれかに記載のコンパイル装置。
【請求項２５】
前記メソッドアドレス格納テーブル最適化手段は、各クラスのメソッドアドレス格納テーブルを比較し、一方のメソッドアドレス格納テーブルに格納されているメソッドアドレス値が、他方のメソッドアドレス格納テーブルの先頭位置に包含されている場合に、包含されている側のメソッドアドレス格納テーブルを削除し、包含されているメソッドアドレス格納テーブルを指していたクラスのメソッドアドレス格納テーブルポインタを、包含している側のメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化する請求項１９から請求項２１までのいずれかに記載のコンパイル装置。
【請求項２６】
前記メソッドアドレス格納テーブル最適化手段は、最適化実施内容を表示させる指令がコンパイラに与えられた場合に、少なくとも最適化の対象となった前記メソッドアドレス格納テーブルを参照していたクラス、最適化前の前記メソッドアドレス格納テーブル、最適化後の前記メソッドアドレス格納テーブルを標準出力に出力する請求項１９から請求項２５までのいずれかに記載のコンパイル装置。
【請求項２７】
前記オブジェクト指向言語をＣ＋＋言語、前記実行時確定メソッドを仮想関数、前記メソッドアドレス格納テーブルを仮想関数テーブル、前記メソッドアドレス格納テーブルポインタを仮想関数テーブルポインタとする請求項１９から請求項２６までのいずれかに記載のコンパイル装置。
【請求項２８】
請求項１から請求項９までのいずれかに記載のコンパイル方法における各ステップをプログラムとして記録したコンピュータ読み取り可能なコンパイル用の記録媒体。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、コンパイル方法、コンパイルプログラム、コンパイル装置およびコンパイル用の記録媒体に関し、特に、Ｃ＋＋言語に代表されるオブジェクト指向言語で記述されたソースプログラムをオブジェクトコードに変換する技術に関する。
【背景技術】
【０００２】
近年のソフトウェア開発においては、プログラムの規模が大規模化してきており、それに伴って保守性、再利用性の高いオブジェクト指向言語が注目されている。オブジェクト指向言語には、起動すべきメソッド（ある機能をオブジェクト指向言語で記述したコード部分）を実行時に決定する機能がある。代表的なオブジェクト指向言語の１つであるＣ＋＋で言えば、仮想関数（virtual function）が該当する。
【０００３】
一般的に、実行時確定メソッドの機能を実装する場合は、出力させるオブジェクトコード内に静的に生成されるメソッドアドレス格納テーブル（各メソッドの先頭アドレスを記録している表）を生成し、各クラスオブジェクトがそのクラスに対応するメソッドアドレス格納テーブルを参照するポインタ（以降、メソッドアドレス格納テーブルポインタと記述）を用いてメソッドアドレス格納テーブルを参照し、さらに実行時確定メソッド毎に決められたインデックス値（以降、メソッドインデックス番号と記述）を用いて動的にメソッド呼び出しを行うことで実現している。
【０００４】
上述した通りメソッドアドレス格納テーブルはコード内に生成されるため、テーブルのサイズが大きくなればなるほど、出力されるオブジェクトコードも比例して大きくなる。出力されるオブジェクトコードのサイズ増加を抑えるため、メソッドアドレス格納テーブルは冗長に生成されないようにしなければならない。
【０００５】
従来のコンパイル方法は、クラス宣言の意味解析処理時に実行時確定メソッドの所属するクラス名と入力ファイル名とを比較し、一致すればメソッドアドレス格納テーブルの実体および宣言をオブジェクトコード内に生成し、一致しなければメソッドアドレス格納テーブルの宣言のみオブジェクトコード内に生成している（例えば、特許文献１参照。図２６参照）。
【特許文献１】特開平６−２６６５６２号公報（第４−５頁、第１図）
【発明の開示】
【発明が解決しようとする課題】
【０００６】
しかしながら従来のコンパイル方法では、クラス名と入力ファイル名との比較による冗長生成の抑制であるので、入力ファイル間で同じクラスに対するメソッドアドレス格納テーブルの冗長生成に対しては対応できるものの、異なるクラス間に対する冗長生成に対しては対応できていない。
【０００７】
本発明は、かかる課題に鑑みてなされたものであり、異なるクラス間に対してもメソッドアドレス格納テーブルの冗長な出力を削除することにより、コード生成効率の良いコンパイル方法を提供することを目的とする。
【課題を解決するための手段】
【０００８】
本発明のある局面にかかわるオブジェクト指向言語のコンパイル方法は、オブジェクト指向言語で記述されたソースプログラムをオブジェクトコードに変換するコンパイル方法であって、
前記ソースプログラムから中間コードを生成する中間コード生成ステップと、
前記中間コードから少なくともメソッドアドレス格納テーブル、前記メソッドアドレス格納テーブルを指しているメソッドアドレス格納テーブルポインタ、前記メソッドアドレス格納テーブルに対応するメソッドインデックス番号を含むメソッドアドレス格納テーブル情報と、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドメソッド名を含むクラス情報と、各メソッドがプログラム内で参照されているかどうかを示す関数参照情報とを抽出する解析対象情報抽出ステップと、
抽出した解析対象情報を解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライド（over ride:再定義）していない場合に、それぞれのクラスの前記メソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した前記両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新することにより前記中間コードを最適化するメソッドアドレス格納テーブル最適化ステップと、
最適化された前記中間コードをオブジェクトコードに変換するオブジェクトコード変換ステップとを含むものである。
【０００９】
この方法によれば、異なるクラス間において冗長に生成されているメソッドアドレス格納テーブルが共通化される。よって、コード生成効率が向上する。
【００１０】
上記のコンパイル方法において、好ましくは、前記解析対象情報抽出ステップは、少なくともファイル名、または関数名、またはクラス名を含む解析範囲限定情報がコンパイラに与えられた場合に、指定された解析範囲に限定して前記メソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出することとする。
【００１１】
この方法によれば、解析範囲の限定が可能になることで解析時間の短縮が図られ、コンパイル時間を短縮することができる。
【００１２】
さらに好ましくは、前記解析対象情報抽出ステップは、定義はされているものの参照はされていない実行時確定メソッドが存在する場合に、定義はされているものの参照はされていないすべての実行時確定メソッドを、クラス情報から削除し、かつすべてのメソッドアドレス格納テーブルより削除し、さらに削除後のメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス番号を更新することとする。
【００１３】
この方法によれば、未参照メソッドの削除により、さらにメソッドアドレス格納テーブル共通化の効果が向上する。
【００１４】
さらに好ましくは、前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも１つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合に、前記基底クラスのメソッドアドレス格納テーブルを削除し、さらに前記基底クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化することとする。
【００１５】
この方法によれば、継承関係にあるクラス間において冗長に生成されているメソッドアドレス格納テーブルが共通化される。よって、コード生成効率が向上する。
【００１６】
さらに好ましくは、前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義していない場合に、新規に実行時確定メソッドを定義していない派生クラスのメソッドアドレス格納テーブルを削除し、さらにその派生クラスのメソッドアドレス格納テーブルポインタを、前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない他方の派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化することとする。
【００１７】
また、好ましくは、前記メソッドアドレス格納テーブル最適化ステップは、基底クラスに対して、少なくとも２つの派生クラスが前記基底クラスの実行時確定メソッドを１つもオーバーライドしていない場合で、かつ両方の派生クラスが新規に実行時確定メソッドを定義している場合で、かつ両方の派生クラスがさらに派生クラスを持たない場合に、派生クラスを持たない一方の派生クラスのメソッドアドレス格納テーブルに、他方の派生クラスで新規に定義した実行時確定メソッドのアドレスを追加したメソッドアドレス格納テーブルを新たに生成し、さらに両方の派生クラスのメソッドアドレス格納テーブルを削除し、さらに両方のメソッドアドレス格納テーブルポインタを、新たに生成したメソッドアドレス格納テーブルの先頭アドレス値に更新し、さらに新たに生成されたメソッドアドレス格納テーブルに対する実行時確定メソッドのインデックス値を更新することにより、前記中間コードを最適化することとする。
【００１８】
これらの方法によれば、兄弟関係にあるクラス間において冗長に生成されているメソッドアドレス格納テーブルが共通化される。よって、コード生成効率が向上する。
【００１９】
また、好ましくは、前記メソッドアドレス格納テーブル最適化ステップは、各クラスのメソッドアドレス格納テーブルを比較し、一方のメソッドアドレス格納テーブルに格納されているメソッドアドレス値が、他方のメソッドアドレス格納テーブルの先頭位置に包含されている場合に、包含されている側のメソッドアドレス格納テーブルを削除し、包含されているメソッドアドレス格納テーブルを指していたクラスのメソッドアドレス格納テーブルポインタを、包含している側のメソッドアドレス格納テーブルの先頭アドレス値に更新することにより、前記中間コードを最適化することとする。
【００２０】
この方法によれば、クラス情報を使用することなく高速にメソッドアドレス格納テーブルが共通化される。
【００２１】
さらに好ましくは、前記メソッドアドレス格納テーブル最適化ステップは、最適化実施内容を表示させる指令がコンパイラに与えられた場合に、少なくとも最適化の対象となった前記メソッドアドレス格納テーブルを参照していたクラス、最適化前の前記メソッドアドレス格納テーブル、最適化後の前記メソッドアドレス格納テーブルを標準出力に出力することにより、前記中間コードの最適化内容をユーザーに与えることとする。
【００２２】
この方法によれば、ユーザーが実際に行われた最適化の内容を確認することができる。
【００２３】
さらに好ましくは、前記オブジェクト指向言語をＣ＋＋言語、前記実行時確定メソッドを仮想関数、前記メソッドアドレス格納テーブルを仮想関数テーブル、前記メソッドアドレス格納テーブルポインタを仮想関数テーブルポインタとする。
【００２４】
この方法によれば、Ｃ＋＋言語で記述されたソースプログラムに対して、効率の良いコードを生成することができる。
【００２５】
なお、本発明は、このような特徴的なステップを有するコンパイル方法として実現することができるだけでなく、当該コンパイル方法に含まれる特徴的なステップを手段とするコンパイラ装置として実現したり、当該コンパイル方法に含まれる特徴的なステップをコンピュータに実行させるコンパイラとして実現したりすることもできる。そして、そのようなコンパイラは、ＣＤ−ＲＯＭ（Compact Disc-Read Only Memory）などの記録媒体やインターネット等の伝送媒体を介して流通させることができるのは言うまでもない。
【発明の効果】
【００２６】
本発明のコンパイル方法によれば、異なるクラス間に対してメソッドアドレス格納テーブルの冗長な出力を削除することにより、コードサイズの小さいオブジェクトコードを生成することができる。
【発明を実施するための最良の形態】
【００２７】
以下、本発明の実施の形態にかかわるコンパイラについて図面を参照しながら説明する。
【００２８】
図１は、コンパイラにより実行される処理のフローチャートである。
【００２９】
コンパイラは、プログラム記憶部Ｄ１に記憶されているヘッダファイルおよびソースプログラムを読み込む（Ｓ１）。コンパイラは、読み込んだソースプログラムの構文を解析し、シンボルテーブルの生成や構文木の生成を行う（Ｓ２）。次に、コンパイラは、生成された構文木を基に、中間コードを生成する（Ｓ３）。その後、コンパイラは、生成された中間コードに対して各種最適化を施す（Ｓ４）。また、コンパイラは、最適化された中間コードに含まれるすべての変数に対してレジスタやメモリなどのハードウェア資源を割り付け（Ｓ５）、資源割付された中間コードをオブジェクトコードに変換してオブジェクトプログラムを生成コード記憶部Ｄ２に出力する（Ｓ６）。
【００３０】
最適化ステップ（Ｓ４）は、解析対象情報抽出ステップ（Ｓ１０）と、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）と、その他の最適化ステップ（Ｓ１２）とを含む。
【００３１】
解析対象情報抽出ステップ（Ｓ１０）は、中間コードを解析し、少なくともメソッドアドレス格納テーブル、メソッドアドレス格納テーブルを指しているメソッドアドレス格納テーブルポインタ、メソッドアドレス格納テーブルに対応するメソッドインデックス番号を含むメソッドアドレス格納テーブル情報と、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドメソッド名を含むクラス情報と、各メソッドがプログラム内で参照されているかどうかを示す関数参照情報とを抽出する。
【００３２】
メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）は、解析対象情報抽出ステップで抽出した解析対象情報を解析し、あるクラスに対して、他のクラスが実行時確定メソッドを１つもオーバーライド（再定義）していない場合に、それぞれのクラスのメソッドアドレス格納テーブルを削除し、両方のクラスに共通に使用可能なメソッドアドレス格納テーブルを生成し、両方のクラスのメソッドアドレス格納テーブルポインタを、生成した両方のクラスに共通に使用可能なメソッドアドレス格納テーブルの先頭アドレス値に更新するステップである。
【００３３】
解析対象情報抽出ステップ（Ｓ１０）ならびにメソッドアドレス格納テーブル最適化ステップ（Ｓ１１）の詳細については後述する。
【００３４】
その他の最適化ステップ（Ｓ１２）は、一般的な最適化ステップであり、本発明の要旨ではないため、その説明は省略する。
【００３５】
なお、ソースプログラム入力ステップ（Ｓ１）、構文解析ステップ（Ｓ２）、中間コード生成ステップ（Ｓ３）、その他の最適化ステップ（Ｓ１２）、資源割付ステップ（Ｓ５）、およびオブジェクト出力ステップ（Ｓ６）については、既存の処理と同様の処理であり本発明の主眼ではない。よって詳細な説明は省略する。
【００３６】
以下、本発明の主眼である解析対象情報抽出ステップ（Ｓ１０）ならびにメソッドアドレス格納テーブル最適化ステップ（Ｓ１１）について説明する。
【００３７】
図２は、解析対象情報抽出ステップ（Ｓ１０）の詳細を示すフローチャートである。
【００３８】
コンパイラは、メソッドアドレス格納テーブル最適化の解析範囲が限定されているか否か判定する。この場合の解析範囲限定の方法は、コマンドラインのオプション指定であってもソースプログラム中に記述するプラグマ指定であっても構わない。またこの場合の解析範囲対象は、翻訳単位（ソースプログラム）に対する範囲対象であっても、関数単位に対する範囲対象であっても、クラス単位に対する範囲対象であっても構わない。
【００３９】
解析範囲が限定されている場合には（Ｓ２１でＹｅｓ）、コンパイラは中間コードから指定範囲のメソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出する（Ｓ２２）。この場合のメソッドアドレス格納テーブル情報とは、少なくともテーブルに格納されているアドレスに該当する実行時確定メソッドと、各メソッドに対応するメソッドインデックス番号、テーブルを参照しているメソッドアドレス格納テーブルポインタを含む。またクラス情報は、少なくとも基底クラス名、派生クラス名、新規実行時確定メソッド名、オーバーライドされているメソッド名を含む。また関数参照情報は、少なくとも定義されているメソッド名が参照されているか否か、もしくは不明かを表す情報を含む。
【００４０】
解析範囲が限定されていない場合には（Ｓ２１でＮｏ）、コンパイラは中間コードからすべてのメソッドアドレス格納テーブル情報、クラス情報、関数参照情報を抽出する（Ｓ２３）。
【００４１】
次に、コンパイラは、定義はされているものの参照はされていない実行時確定メソッドが存在するか否かを判定する（Ｓ２４）。存在する場合には（Ｓ２４でＹｅｓ）、コンパイラは未参照の実行時確定メソッドのアドレスを、前ステップ（Ｓ２２orＳ２３）で抽出したすべてのクラス情報ならびにメソッドアドレス格納テーブル情報から削除し（Ｓ２５）、削除後のメソッドアドレス格納テーブルのメソッドインデックス値を更新する（Ｓ２６）。
【００４２】
次に、コンパイラは、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）を実施する。
【００４３】
図３は、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）の詳細を示すフローチャートである。
【００４４】
コンパイラは、メソッドアドレス格納テーブル最適化の解析にクラスの継承関係を使用するか否かを判定する（Ｓ２７）。解析にクラスの継承関係を使用するか否かは、ユーザーによる指定（前記オプション指定やプラグマ指定）で選択しても構わないし、コンパイラが静的に動作を決めていても構わない。
【００４５】
クラスの継承関係を使用すると判定された場合には（Ｓ２７でＹｅｓ）、コンパイラは親子クラス解析サブステップ（Ｓ２８）を実施する。
【００４６】
図４は、親子クラス解析サブステップ（Ｓ２８）の詳細を示すフローチャートである。
【００４７】
コンパイラは、解析範囲の基底クラスと派生クラスの組み合わせについて、以下のループ処理（Ｓ４０）を繰り返す。コンパイラは、基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスが少なくとも１つ存在するか否かを判定する（Ｓ４１）。存在する場合には（Ｓ４１でＹｅｓ）、基底クラスのメソッドアドレス格納テーブルを削除し（Ｓ４２）、基底クラスのメソッドアドレス格納テーブルポインタを含めた、削除したメソッドアドレス格納テーブルを参照していたすべてのメソッドアドレス格納テーブルポインタを、１つもオーバーライドしていない派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新の後（Ｓ４３）、次の基底クラスと派生クラスとの組み合わせについてループ処理（Ｓ４０）を繰り返す。存在しない場合には（Ｓ４１でＮｏ）、次の基底クラスと派生クラスとの組み合わせについてループ処理（Ｓ４０）を繰り返す。
【００４８】
次に、コンパイラは、兄弟クラス解析サブステップ（Ｓ２９）を実施する。
【００４９】
図５および図６は、兄弟クラス解析サブステップ（Ｓ２９）の詳細を示すフローチャートである。
【００５０】
コンパイラは、解析範囲の基底クラスと派生クラスの組み合わせについて、以下のループ処理（Ｓ５０）を繰り返す。コンパイラは、基底クラスの実行時確定メソッドを１つもオーバーライドしていない派生クラスが少なくとも２つ存在するか否かを判定する（Ｓ５１）。存在する場合には（Ｓ５１でＹｅｓ）、コンパイラは、オーバーライドしていない派生クラスの組み合わせについて、さらにループ処理（Ｓ５２）を繰り返す。存在しない場合には（Ｓ５１でＮｏ）、次の基底クラスと派生クラスとの組み合わせについてループ処理（Ｓ５０）を繰り返す。
【００５１】
ループ処理（Ｓ５２）では、コンパイラは、両方の派生クラスが新規に実行時確定メソッドを定義しているか否かを判定する（Ｓ５３）。両方の派生クラスが新規に実行時確定メソッドを定義している場合には（Ｓ５３でＹｅｓ）、コンパイラは、両方の派生クラスがさらに派生クラスを持つか否かを判定する（Ｓ５６）。
【００５２】
両方の派生クラスが新規に実行時確定メソッドを定義していない場合には（Ｓ５３でＮｏ）、コンパイラは、新規に実行時確定メソッドを定義していない派生クラス（両方定義していない場合はどちらか一方）のメソッドアドレス格納テーブルを削除し（Ｓ５４）、削除した側の派生クラスのメソッドアドレス格納テーブルポインタを含めた、削除したメソッドアドレス格納テーブルを参照していたすべてのメソッドアドレス格納テーブルポインタを、基底クラスの実行時確定メソッドを１つもオーバーライドしていない他方の派生クラスのメソッドアドレス格納テーブルの先頭アドレス値に更新した後（Ｓ５５）、次のオーバーライドしていない派生クラスの組み合わせについて、ループ処理（Ｓ５２）を繰り返す。
【００５３】
両方の派生クラスがさらに派生クラスを持つ場合には（Ｓ５６でＹｅｓ）、次のオーバーライドしていない派生クラスの組み合わせについて、ループ処理（Ｓ５２）を繰り返す。
【００５４】
両方の派生クラスがさらに派生クラスを持たない場合には（Ｓ５６でＮｏ）、コンパイラは、派生クラスを持たない一方の派生クラス（両方派生クラスを持たない場合は、どちらか一方）のメソッドアドレス格納テーブルに、他方の派生クラスで新規に定義した実行時確定メソッドのアドレスを追加したメソッドアドレス格納テーブルを新たに生成する（Ｓ５７）。次に、コンパイラは、両方の派生クラスのメソッドアドレス格納テーブルを削除する（Ｓ５８）。次に、コンパイラは、両方のメソッドアドレス格納テーブルポインタを含めた、削除したメソッドアドレス格納テーブルを参照していたすべてのメソッドアドレス格納テーブルポインタを、新たに生成したメソッドアドレス格納テーブルの先頭アドレス値に更新する（Ｓ５９）。次に、コンパイラは、新たに生成されたメソッドアドレス格納テーブルに対する実行時確定メソッドのメソッドインデックス値を更新し（Ｓ６０）、次のオーバーライドしていない派生クラスの組み合わせについて、ループ処理（Ｓ５２）を繰り返す。すべてのループ処理（Ｓ５０、Ｓ５２）を実施した後、判定処理（Ｓ３１）に移る。
【００５５】
クラスの継承関係を使用しないと判定された場合には（Ｓ２７でＮｏ）、コンパイラはメソッドアドレス包含解析サブステップ（Ｓ３０）を実施する。
【００５６】
図７は、メソッドアドレス包含解析サブステップ（Ｓ３０）の詳細を示すフローチャートである。
【００５７】
コンパイラは、解析範囲のクラスのメソッドアドレス格納テーブルの組み合わせに対して、以下のループ処理（Ｓ７０）を繰り返す。コンパイラは、一方のメソッドアドレス格納テーブルに格納されているメソッドアドレス値が、他方のメソッドアドレス格納テーブルの先頭位置に包含されているか否かを判定する（Ｓ７１）。包含されている場合には（Ｓ７１でＹｅｓ）、包含されている側のメソッドアドレス格納テーブルを削除し（Ｓ７２）、包含されているメソッドアドレス格納テーブルを指していたクラスのメソッドアドレス格納テーブルポインタを、包含している側のメソッドアドレス格納テーブルの先頭アドレス値に更新の後（７３）、次のメソッドアドレス格納テーブルの組み合わせについてループ処理（Ｓ７０）を繰り返す。包含されてない場合には（Ｓ７１でＮｏ）、次のメソッドアドレス格納テーブルの組み合わせについてループ処理（Ｓ７０）を繰り返す。すべてのループ処理（Ｓ７０）を実施した後、判定処理（Ｓ３１）に移る。
【００５８】
判定処理（Ｓ３１）は、最適化の内容を表示させるか否かを判定する。この場合の最適化内容表示指定の方法は、コマンドラインのオプション指定であってもソースプログラム中に記述するプラグマ指定であっても構わない。
【００５９】
最適化の内容を表示させる指令を与えている場合には（Ｓ３１でＹｅｓ）、コンパイラは、最適化の対象となったメソッドアドレス格納テーブルを参照していたクラス、最適化前のメソッドアドレス格納テーブル、最適化後のメソッドアドレス格納テーブルを標準出力に出力し、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）を終了する。
【００６０】
最適化の内容を表示させる指令を与えていない場合には（Ｓ３１でＮｏ）、コンパイラはそのまま何もせずに、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）を終了する。
【００６１】
以上のような解析対象情報抽出ステップ（Ｓ１０）と、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）と、その他の最適化ステップ（Ｓ１２）とを含む最適化ステップ（Ｓ４）を施した中間コードに対して、資源割付処理（Ｓ５）およびオブジェクトプログラム出力処理（Ｓ６）を行うことにより、最終的に生成されるオブジェクトプログラムのオブジェクトコードのサイズが削減される。
【００６２】
以下、Ｃ＋＋言語による具体例を参照しながらメソッドアドレス格納テーブル最適化ステップについてより詳細に説明する。具体例では、実行時確定メソッドは仮想関数、メソッドアドレス格納テーブルは仮想関数テーブル(vtbl)、メソッドアドレス格納テーブルポインタは仮想関数テーブルポインタ（vptr）として話を進める。
【００６３】
（具体例１）
図８は、プログラム記憶部Ｄ１に記憶されているヘッダファイルおよびソースプログラムの一例を示す。以下では、このヘッダファイルおよびソースプログラムを入力した場合のコンパイラの動作を説明する。
【００６４】
図８に示すヘッダファイル「class.h」には、クラスＡ、クラスＢ、クラスＣ、クラスＤ、クラスＥ、クラスＦの定義が記載されている。各クラスには、それぞれのコンストラクタ、デストラクタが定義されている。クラスＡでは、仮想関数vfunc1,vfunc2が定義されている。クラスＢは、クラスＡを継承しており、仮想関数vfunc3が定義されている。クラスＣは、クラスＢを継承している。クラスＤは、クラスＢを継承しており、仮想関数vfunc4が定義されている。クラスＥは、クラスＢを継承しており、仮想関数vfunc5が定義されている。クラスＦは、クラスＡを継承しており、クラスＡで定義している仮想関数vfunc2をオーバーライド（再定義）している。
【００６５】
図８に示すソースファイル「file1.cpp」、「file2.cpp」では、最初に#inlude指令によって、「class.h」のヘッダファイルを読み込んでいる。また、外部関数f、g、h、i、mainが定義されており、関数内で仮想関数呼び出しが行われている。
【００６６】
従来の方法では、クラス間における仮想関数テーブルの最適化は実施されないので、各クラスに対して仮想関数テーブルがそのまま出力されることになる。図９に各クラスに対する仮想関数テーブルと、各クラスにおける仮想関数のインデックス番号を図示する。各クラスの仮想関数テーブルには、各クラスが呼び出すことのできる仮想関数のアドレスがすべて格納されていることがわかる。
【００６７】
次に、本実施の形態における具体例を示す。前提として、「file1.cpp」の範囲で解析すること、クラスの継承関係を使用すること、最適化内容を表示することが、ユーザーよりコンパイラに指令されているものとする。
【００６８】
まず解析対象情報抽出ステップ（Ｓ１０）が実施されると、解析範囲が限定されているか否かの判定（Ｓ２１）が行われる。前記した前提により限定がされているので、「file1.cpp」の範囲における仮想関数テーブル情報、クラス情報、関数参照情報が抽出される（Ｓ２２）。図１０に、抽出されたクラス情報、ならびに関数参照情報を示す。また、抽出された仮想関数テーブル情報は、図９と同じである。
【００６９】
次に、未参照の仮想関数が存在するか否かの判定が実施される（Ｓ２４）。図１０の関数参照情報が示すとおり、「file1.cpp」の範囲における解析では、vfunc1が参照されていることは判明しているものの、その他の仮想関数が参照されているかどうかは不明である。よって、特に仮想関数テーブルから仮想関数アドレスは削除されない。
【００７０】
次に、コンパイラは、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）を実施する。まず、クラスの継承関係を使用するか否かの判定が実施される（Ｓ２７）。前記した前提によりクラスの継承関係を使用するので、次の親子クラス解析サブステップ（Ｓ２８）が実施される。
【００７１】
親子クラス解析サブステップ（Ｓ２８）では、解析範囲の基底クラスと派生クラスの組み合わせに対して、以下の処理が実施される（Ｓ４０）。まずクラスＡとクラスＢ、クラスＦの基底クラス、派生クラスの組み合わせについて、基底クラスの仮想関数を１つもオーバーライドしていない派生クラスが少なくとも１つ存在するか否かの判定が実施される（Ｓ４１）。
【００７２】
図１０のクラス情報によれば、クラスＦは仮想関数vfunc2をオーバーライドしているものの、クラスＢは１つもオーバーライドしていないので、図１１に示すように、基底クラスであるクラスＡの仮想関数テーブルが削除され（Ｓ４２）、クラスＡの仮想関数テーブルポインタ（vptr）を、クラスＢの仮想関数テーブルを指すように更新される（Ｓ４３）。
【００７３】
次にクラスＢとクラスＣ、クラスＤ、クラスＥの基底クラス、派生クラスの組み合わせについて、同様に判定処理（Ｓ４１）を実施する。図１０のクラス情報によれば、クラスＣ、クラスＤ、クラスＥ、すべてオーバーライドしていない。よって図１２に示すように、基底クラスであるクラスＢの仮想関数テーブルが削除され（Ｓ４２）、クラスＢの仮想関数テーブルポインタ、および削除された仮想関数テーブルを参照していたクラスＡの仮想関数テーブルポインタを、ここでは検索対象の最初であったクラスＣの仮想関数テーブルを指すように更新される（Ｓ４３）。すべての対象に対してループ処理（Ｓ４０）が終了したので、次に、兄弟クラス解析サブステップ（Ｓ２９）が実施される。
【００７４】
兄弟クラス解析サブステップ（Ｓ２９）では、解析範囲の基底クラスと派生クラスの組み合わせに対して、以下の処理が実施される（Ｓ５０）。まずクラスＡとクラスＢ、クラスＦの基底クラス、派生クラスの組み合わせについて、基底クラスの仮想関数を１つもオーバーライドしていない派生クラスが少なくとも２つ存在するか否かの判定が実施される（Ｓ５１）。
【００７５】
図１０のクラス情報によれば、２つは存在しないことがわかるので、次の組み合わせであるクラスＢと、クラスＣ、クラスＤ、クラスＥの組み合わせについて、同様に判定（Ｓ５１）を実施する。図１０のクラス情報によれば、クラスＣ、クラスＤ、クラスＥは、すべてオーバーライドしていない。よってオーバーライドしていない派生クラスの組み合わせであるクラスＣ、クラスＤ、クラスＥについて、以下の処理を繰り返す（Ｓ５２）。
【００７６】
まずクラスＣ、クラスＤ両方のクラスが、新規に仮想関数を定義しているか否かを判定する（Ｓ５３）。図１０のクラス情報によれば、クラスＣは新規の仮想関数を定義していないので、この場合は図１３に示すとおり、クラスＣの仮想関数テーブルを削除し（Ｓ５４）、クラスＣの仮想関数テーブルポインタ、および削除された仮想関数テーブルを参照していたクラスＡ、クラスＢの仮想関数テーブルポインタを、クラスＤの仮想関数テーブルを指すように更新される（Ｓ５５）。
【００７７】
次に、クラスＤ、クラスＥ両方のクラスが、新規に仮想関数を定義しているか否かを判定する（Ｓ５３）。図１０のクラス情報によれば、クラスＤ、クラスＥ、両方ともに新規の仮想関数を定義しているので、両方の派生クラスが、さらに派生クラスを持つか否かの判定が実施される（Ｓ５６）。図１０のクラス情報によれば、クラスＤ、クラスＥ、いずれも派生クラスを持たない。よって新規に仮想関数テーブルを生成する処理（Ｓ５７）の基本となるクラスにどちらを選択してもよい。ここでは、図１４に示すように、クラスＤの仮想関数テーブルに、クラスＥの仮想関数テーブルで新規に定義した仮想関数vfunc5のアドレスを追加した仮想関数テーブルを新たに生成し（Ｓ５７）、両方のクラスの仮想関数テーブルを削除し（Ｓ５８）、両方の仮想関数アドレスポインタおよび削除した仮想関数テーブルを参照していたクラスＡ、クラスＢ、クラスＣの仮想関数アドレスポインタを、新たに生成した仮想関数テーブルを指すように更新するようにする。また、図１４に示すように、関数インデックス番号についても、新たに生成した仮想関数テーブルをもとに更新を行う（Ｓ６０）。すべての対象に対してループ処理（Ｓ５０）が終了したので、次に、ユーザーが最適化内容を表示させる指令を与えているか否かを判定する処理（Ｓ３１）が実施される。
【００７８】
前記した前提のとおり、最適化内容を表示させる指令が与えられているので、図１５に示すように、最適化の対象となった仮想関数テーブルを参照していたクラス、最適化前の仮想関数テーブル、最適化後の仮想関数テーブルが標準出力に出力される。
【００７９】
以上の処理によってメソッドアドレス格納テーブルが最適化された中間コードを得ることができる。最適化を実施しなかった場合の中間コードと、最適化を実施した場合の中間コードからそれぞれアセンブラを出力させた結果を図１６に示す。図１６に示すとおり、最適化を実施したことにより、実施しない場合と比較して４４byteのコードサイズ削減が実現できていることがわかる（コードサイズは“ＤＤ”の個数に「４」を掛算したものになる）。
【００８０】
このように、従来では各クラスに対してそれぞれ出力させていた仮想関数テーブルを、本最適化によりまとめて出力できていることがわかり、このためコードサイズが削減できていることがわかる。
【００８１】
（具体例２）
具体例１の前提条件のうち、クラスの継承関係を使用しないという前提の場合を考える。この場合、クラスの継承関係を使用するか否かの判定処理（Ｓ２７）までは、具体例１と同様の処理が行われ、図９の仮想関数テーブル情報が抽出されている。次に、メソッドアドレス包含解析サブステップ（Ｓ３０）が実施されることになる。
【００８２】
メソッドアドレス包含解析サブステップ（Ｓ３０）では、解析範囲のクラスの各仮想関数テーブルの組み合わせに対して、以下の処理を繰り返す（Ｓ７０）。
【００８３】
まず、クラスＡとクラスＢの仮想関数テーブルに対して、一方の仮想関数テーブルに格納されている仮想関数アドレスが、他方の仮想関数アドレステーブルの先頭位置に包含されているか否かの判定を行う（Ｓ７１）。図９によれば、クラスＡの仮想関数テーブルに格納されている仮想関数アドレスは、クラスＢの仮想関数テーブルに包含されていることがわかる。よって、包含されている側のクラスＡの仮想関数テーブルを削除し（Ｓ７２）、削除したテーブルを参照していた仮想関数テーブルポインタを包含している側のクラスＢの仮想関数テーブルを指すように更新する（Ｓ７３）。この結果、具体例１で示した図１１の結果と同じになる。同様に、クラスＢとクラスＣに対してＳ７０を実施した結果が図１２、クラスＣとクラスＤに対してＳ７０を実施した結果が図１３となる。
【００８４】
以上の処理によって、メソッドアドレス格納テーブルを共通化させた中間コードを得ることができる。最適化を実施しなかった場合の中間コードと、最適化を実施した場合の中間コードからそれぞれアセンブラを出力させた結果を図１７に示す。図１７に示すとおり、最適化を実施したことにより、実施しない場合と比較して３２byteのコードサイズ削減が実現できていることがわかる。
【００８５】
このように、クラスの継承関係を使用しない場合は、継承関係を使用する場合と比較して最適化効率は劣るものの、処理アルゴリズムが単純であり、クラス継承関係を解析する必要がなくなるため、高速な最適化処理が可能である。
【００８６】
（具体例３）
具体例１の前提条件のうち、「file1.cpp」の範囲で解析する指令を取りやめ、ソースプログラム全体に対して解析を行う場合を考える。
【００８７】
まず解析対象情報抽出ステップ（Ｓ１０）が実施されると、解析範囲が限定されているか否かの判定（Ｓ２１）が行われる。前記した前提により限定は存在しないので、ソースプログラム全体に対する仮想関数テーブル情報、クラス情報、関数参照情報が抽出される（Ｓ２３）。図１８に、抽出されたクラス情報、ならびに関数参照情報を示す。また、この時点で抽出された仮想関数テーブル情報は、具体例１と同様の図９に示すとおりである。
【００８８】
次に、未参照の仮想関数が存在するか否かの判定が実施される（Ｓ２４）。図１８の関数参照情報が示すとおり、プログラム全体に対する解析では、仮想関数vfunc2が参照されていないことが判明している。よって、図１８で示したクラス情報のうち、未参照仮想関数であるvfunc2の情報ならびに仮想関数テーブルから未参照仮想関数であるvfunc2の仮想関数アドレスが削除され（Ｓ２５）、仮想関数インデックス番号が削除後の仮想関数テーブルをもとに更新される（Ｓ２６）。図１９に、未参照仮想関数を削除したクラス情報、図２０に未参照仮想関数アドレスを仮想関数テーブルから削除し、インデックス番号を更新した結果を示す。
【００８９】
次に、コンパイラは、メソッドアドレス格納テーブル最適化ステップ（Ｓ１１）を実施する。まず、クラスの継承関係を使用するか否かの判定が実施される（Ｓ２７）。前記した前提により、クラスの継承関係を使用するので、次の親子クラス解析サブステップ（Ｓ２８）が実施される。
【００９０】
親子クラス解析サブステップ（Ｓ２８）では、解析範囲の基底クラスと派生クラスの組み合わせに対して、以下の処理が実施される（Ｓ４０）。まずクラスＡとクラスＢ、クラスＦの基底クラス、派生クラスの組み合わせについて、基底クラスの仮想関数を１つもオーバーライドしていない派生クラスが少なくとも１つ存在するか否かの判定が実施される（Ｓ４１）。図１９のクラス情報によれば、クラスＢ、クラスＦともに１つもオーバーライドしていない。よってここでは、具体例１と同様、基底クラスであるクラスＡの仮想関数テーブルが削除され（Ｓ４２）、クラスＡの仮想関数テーブルポインタ（vptr）を、クラスＢの仮想関数テーブルを指すように更新されるものとする（Ｓ４３）。
【００９１】
同様に、クラスＢとクラスＣ、クラスＤ、クラスＥの基底クラス、派生クラスの組み合わせについて、判定処理（Ｓ４１）を実施する。具体例１と同様に、基底クラスであるクラスＢの仮想関数テーブルが削除され（Ｓ４２）、クラスＢの仮想関数テーブルポインタ、および削除された仮想関数テーブルを参照していたクラスＡの仮想関数テーブルポインタを、ここでは検索対象の最初であったクラスＣの仮想関数テーブルを指すように更新される（Ｓ４３）。この時点での仮想関数テーブルは、図２１に示すとおりである。すべての対象に対してループ処理（Ｓ４０）が終了したので、次に、兄弟クラス解析サブステップ（Ｓ２９）が実施される。
【００９２】
兄弟クラス解析サブステップ（Ｓ２９）では、解析範囲の基底クラスと派生クラスの組み合わせに対して、以下の処理が実施される（Ｓ５０）。まずクラスＡとクラスＢ、クラスＦの基底クラス、派生クラスの組み合わせについて、基底クラスの仮想関数を１つもオーバーライドしていない派生クラスが少なくとも２つ存在するか否かの判定が実施される（Ｓ５１）。もともと未参照の仮想関数アドレスを削除する前のクラス情報（図１８）での場合は、クラスＦでvfunc2をオーバーライドしていたために判定結果が偽となっていた。しかし今回は未参照の仮想関数が削除されているため、図１９のクラス情報により、クラスＢ、クラスＦ、ともにクラスＡの仮想関数をオーバーライドしていないこととなり、２つ存在すると判定される。よって、クラスＢとクラスＦの組み合わせで、以下の処理（Ｓ５２）が繰り返される。
【００９３】
まず、クラスＢ、クラスＦ両方のクラスが、新規に仮想関数を定義しているか否かを判定する（Ｓ５３）。図１９のクラス情報によれば、クラスＦは新規の仮想関数を定義していないので、この場合はクラスＦの仮想関数テーブルを削除し（Ｓ５４）、クラスＦの仮想関数テーブルポインタを、クラスＣの仮想関数テーブル（この段階では、すでにクラスＡ、クラスＢと共用の仮想関数テーブルとなっている）を指すように更新される（Ｓ５５）。この段階での仮想関数テーブル情報を図２２に示す。
【００９４】
同様に、次の組み合わせであるクラスＢと、クラスＣ、クラスＤ、クラスＥの組み合わせに対して、判定（Ｓ５１）を実施する。図１８のクラス情報によれば、クラスＣ、クラスＤ、クラスＥ、すべてオーバーライドしていない。よってオーバーライドしていない派生クラスの組み合わせであるクラスＣ、クラスＤ、クラスＥについて、以下の処理を繰り返す（Ｓ５２）。
【００９５】
まずクラスＣ、クラスＤ両方のクラスが、新規に仮想関数を定義しているか否かを判定する（Ｓ５３）。図１９のクラス情報によれば、クラスＣは新規の仮想関数を定義していないので、この場合はクラスＣの仮想関数テーブルを削除し（Ｓ５４）、クラスＣの仮想関数テーブルポインタ、および削除された仮想関数テーブルを参照していたクラスＡ、クラスＢ、クラスＦの仮想関数テーブルポインタを、クラスＤの仮想関数テーブルを指すように更新される（Ｓ５５）。この段階での仮想関数テーブル情報を図２３に示す。
【００９６】
次に、クラスＤ、クラスＥ両方のクラスが、新規に仮想関数を定義しているか否かを判定する（Ｓ５３）。図１９のクラス情報によれば、クラスＤ、クラスＥ、両方ともに新規の仮想関数を定義しているので、両方の派生クラスが、さらに派生クラスを持つか否かの判定が実施される（Ｓ５６）。図１９のクラス情報によれば、クラスＤ、クラスＥ、いずれも派生クラスを持たない。よって新規に仮想関数テーブルを生成する処理（Ｓ５７）の基本となるクラスにどちらを選択してもよい。ここでは、図２４に示すように、クラスＤの仮想関数テーブルに、クラスＥの仮想関数テーブルで新規に定義した仮想関数vfunc5のアドレスを追加した仮想関数テーブルを新たに生成し（Ｓ５７）、両方のクラスの仮想関数テーブルを削除し（Ｓ５８）、両方の仮想関数アドレスポインタおよび削除した仮想関数テーブルを参照していたクラスＡ、クラスＢ、クラスＣ、クラスＦの仮想関数アドレスポインタを、新たに生成した仮想関数テーブルを指すように更新するようにする。また、図２４に示すように、関数インデックス番号についても、新たに生成した仮想関数テーブルをもとに更新を行う（Ｓ６０）。すべての対象に対してループ処理（Ｓ５０）が終了したので、次に、ユーザーが最適化内容を表示させる指令を与えているか否かを判定する処理（Ｓ３１）が実施される。以降の処理は、具体例１と同様であるので省略する。
【００９７】
以上の処理によってメソッドアドレス格納テーブルが最適化された中間コードを得ることができる。最適化を実施しなかった場合の中間コードと、最適化を実施した場合の中間コードからそれぞれアセンブラを出力させた結果を図２５に示す。図２５に示すとおり、最適化を実施したことにより、実施しない場合と比較して５６byteのコードサイズ削減が実現できていることがわかる。
【００９８】
このように、未参照の仮想関数を削除することで仮想関数テーブルのサイズを小さくすることが可能となり、また具体例３のように、オーバーライドが行われている関数（vfunc2）が未参照の場合は、さらに仮想関数テーブルをまとめて出力できるためコードサイズが削減できていることがわかる。
【００９９】
以上説明したように、本実施の形態によると異なるクラス間に対してメソッドアドレス格納テーブルの冗長な出力を削除することにより、コードサイズの小さいオブジェクトコードを生成することができる。
【産業上の利用可能性】
【０１００】
本発明にかかるコンパイル方法は、携帯電話やＰＤＡ（Personal DigitalAssistant）等のコードサイズの小さなオブジェクトコードを必要とする組み込み機器用のコンパイル方法等に適用可能である。
【図面の簡単な説明】
【０１０１】
【図１】本発明の実施の形態にかかるコンパイラにより実行される処理のフローチャート
【図２】本発明の実施の形態における解析対象情報抽出ステップの詳細を示すフローチャート
【図３】本発明の実施の形態におけるメソッドアドレス格納テーブル最適化ステップの詳細を示すフローチャート
【図４】本発明の実施の形態における親子クラス解析サブステップの詳細を示すフローチャート
【図５】本発明の実施の形態における兄弟クラス解析サブステップの詳細を示すフローチャート（その１）
【図６】本発明の実施の形態における兄弟クラス解析サブステップの詳細を示すフローチャート（その２）
【図７】本発明の実施の形態におけるメソッドアドレス包含解析サブステップの詳細を示すフローチャート
【図８】本発明の実施の形態における具体例１、２、３で用いられるプログラム記憶部に記憶されているソースプログラムの一例
【図９】本発明の実施の形態における最適化を実施する前の仮想関数テーブル情報の一例
【図１０】本発明の実施の形態における具体例１、２のクラス情報の一例
【図１１】本発明の実施の形態における具体例１の親子クラス解析サブステップのループ１回目実施後の仮想関数テーブル情報の一例、および具体例２のメソッドアドレス包含解析サブステップのループ１回目実施後の仮想関数テーブル情報の一例
【図１２】本発明の実施の形態における具体例１の親子クラス解析サブステップのループ２回目実施後の仮想関数テーブル情報の一例、および具体例２におけるメソッドアドレス包含解析サブステップのループ２回目実施後の仮想関数テーブル情報の一例
【図１３】本発明の実施の形態における具体例１の兄弟クラス解析サブステップのループ１回目実施後の仮想関数テーブル情報の一例、および具体例２におけるメソッドアドレス包含解析サブステップのループ３回目実施後の仮想関数テーブル情報の一例
【図１４】本発明の実施の形態における具体例１の兄弟クラス解析サブステップのループ２回目実施後の仮想関数テーブル情報の一例
【図１５】本発明の実施の形態における具体例１の最適化情報表示結果の一例
【図１６】本発明の実施の形態における具体例１の最適化を実施する前の中間コードから生成したアセンブラコードの一例、ならびに最適化を実施した後の中間コードから生成したアセンブラコードの一例
【図１７】本発明の実施の形態における具体例２の最適化を実施する前の中間コードから生成したアセンブラコードの一例、ならびに最適化を実施した後の中間コードから生成したアセンブラコードの一例
【図１８】本発明の実施の形態における具体例３のクラス情報の一例
【図１９】本発明の実施の形態における具体例３の未参照仮想関数削除後のクラス情報の一例
【図２０】本発明の実施の形態における具体例３の未参照仮想関数削除後のメソッドアドレス格納テーブル情報の一例
【図２１】本発明の実施の形態における具体例３の親子クラス解析サブステップのループ２回目実施後の仮想関数テーブル情報の一例
【図２２】本発明の実施の形態における具体例３の親子クラス解析サブステップのループ３回目実施後の仮想関数テーブル情報の一例
【図２３】本発明の実施の形態における具体例３の兄弟クラス解析サブステップのループ１回目実施後の仮想関数テーブル情報の一例
【図２４】本発明の実施の形態における具体例３の兄弟クラス解析サブステップのループ２回目実施後の仮想関数テーブル情報の一例
【図２５】本発明の実施の形態における具体例３の最適化を実施する前の中間コードから生成したアセンブラコードの一例、ならびに最適化を実施した後の中間コードから生成したアセンブラコードの一例
【図２６】従来の技術の説明図
【符号の説明】
【０１０２】
Ｄ１  プログラム記憶部
Ｄ２  生成コード記憶部
【図１】
2006163686.tif 000003
【図２】
2006163686.tif 000004
【図３】
2006163686.tif 000005
【図４】
2006163686.tif 000006
【図５】
2006163686.tif 000007
【図６】
2006163686.tif 000008
【図７】
2006163686.tif 000009
【図８】
2006163686.tif 000010
【図９】
2006163686.tif 000011
【図１０】
2006163686.tif 000012
【図１１】
2006163686.tif 000013
【図１２】
2006163686.tif 000014
【図１３】
2006163686.tif 000015
【図１４】
2006163686.tif 000016
【図１５】
2006163686.tif 000017
【図１６】
2006163686.tif 000018
【図１７】
2006163686.tif 000019
【図１８】
2006163686.tif 000020
【図１９】
2006163686.tif 000021
【図２０】
2006163686.tif 000022
【図２１】
2006163686.tif 000023
【図２２】
2006163686.tif 000024
【図２３】
2006163686.tif 000025
【図２４】
2006163686.tif 000026
【図２５】
2006163686.tif 000027
【図２６】
2006163686.tif 000028