(57)【要約】      （修正有）【課題】コード列内のメソッド境界におけるvirtual call guardを最適化する技術を提供する。【解決手段】最適化装置２１０は、コード列に含まれる各仮想関数に対しメソッド・テストを挿入する挿入部２１２と、挿入処理済のコード列の実行において各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得する取得部２１４と、コード列に含まれる各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対しメソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、挿入した前記メソッド・テストに代えて、対応するレシーバ・オブジェクトの記録時のクラス及び実行時のクラスを許可すべきクラスとするクラス・テストを挿入する最適化部２１８とを含む。【選択図】図２
2013235386.tif 000002
【特許請求の範囲】
【請求項１】
コンピュータ処理により、記録されたトレース又はスペシャライズされた直線実行パス（以下、まとめて「コード列」という）を最適化する最適化方法であって、
（ａ）記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対しメソッド・テストを挿入するステップと、
（ｂ）前記コード列の実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得するステップと、
（ｃ）前記コード列に含まれる前記各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、前記メソッド・テストに代えて、前記対応するレシーバ・オブジェクトの記録時のクラス及び前記実行時のクラスを許可すべきクラスとするクラス・テストを挿入することにより、前記コード列を最適化するステップと、
を含む最適化方法。
【請求項２】
ステップ（ｃ）において、許可すべきクラスとするクラスの数が所定数を超える場合に複数の許可すべきクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラスとして追加する、請求項１に記載の最適化方法。
【請求項３】
ステップ（ｃ）において、使用するレシーバ・オブジェクトが同一である複数の仮想関数については、前記コード列内において最初に実行される仮想関数に対してのみ前記クラス・テストを挿入し、残りの仮想関数に対する前記クラス・テストを省略する、請求項２に記載の最適化方法。
【請求項４】
前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスは、前記コード列に挿入されたすべての前記メソッド・テストの成功を条件にプロファイルされる、請求項３に記載の最適化方法。
【請求項５】
コンピュータ処理により、記録されたトレース又はスペシャライズされた直線実行パス（以下、「コード列」という）を最適化する最適化方法であって、
（ａ）記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対し、該仮想関数の呼び出しに使用されるレシーバ・オブジェクトの記録時のクラスを許可すべきクラスとするクラス・テストと、該クラス・テストの失敗をその実行の条件とするメソッド・テストとを挿入するステップと、
（ｂ）挿入処理済みの前記コード列の実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得するステップと、
（ｃ）前記コード列に含まれる前記各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、対応する前記クラス・テストが許可するクラスに前記実行時のクラスを追加することにより前記コード列を最適化するステップと、
を含む最適化方法。
【請求項６】
最適化されたコード列の実行に対してステップ（ｂ）及び（ｃ）を繰り返す、請求項５に記載の最適化方法。
【請求項７】
ステップ（ｂ）において、各仮想関数に対して挿入された前記メソッド・テストのプロファイルされたテスト結果を合わせて取得し、ステップ（ｃ）において、前記メソッド・テストの結果が失敗であった仮想関数が使用するレシーバ・オブジェクトの実行時のクラスを、対応するクラス・テストに拒絶すべきクラスとして追加する、請求項６に記載の最適化方法。
【請求項８】
ステップ（ｃ）において、追加される許可すべきクラス又は拒絶すべきクラスの数が所定数を超える場合に当該所定数を超える複数のクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラス又は拒絶すべきクラスとして追加する、請求項７に記載の最適化方法。
【請求項９】
コンピュータに、請求項１乃至８のいずれか一項に記載の最適化方法の各ステップを実行させるための最適化プログラム。
【請求項１０】
記録されたトレース又はスペシャライズされた直線実行パス（以下、まとめて「コード列」という）を最適化する最適化装置であって、
記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対しメソッド・テストを挿入する挿入部と、
前記メソッド・テストを挿入された前記コード列の実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得する取得部と、
前記コード列に含まれる前記各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、前記メソッド・テストに代えて、前記対応するレシーバ・オブジェクトの記録時のクラス及び前記実行時のクラスを許可すべきクラスとするクラス・テストを挿入する最適化部と、
を含む最適化装置。
【請求項１１】
前記最適化部は、許可すべきクラスとするクラスの数が所定数を超える場合に当該所定数を超える複数のクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラスとして追加する、請求項１０に記載の最適化装置。
【請求項１２】
前記最適化部は、レシーバ・オブジェクトが同一である複数の仮想関数については、前記コード列内において最初に実行される仮想関数に対してのみ前記クラス・テストを挿入し、残りの仮想関数に対する前記クラス・テストを省略する、請求項１１に記載の最適化装置。
【請求項１３】
記録されたトレース又はスペシャライズされた直線実行パス（以下、まとめて「コード列」という）を最適化する最適化装置であって、
記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対し、該仮想関数の呼び出しに使用されるレシーバ・オブジェクトの記録時のクラスを許可すべきクラスとするクラス・テストと、該クラス・テストの失敗をその実行の条件とするメソッド・テストとを挿入する挿入部と、
挿入処理済みの前記コード列の実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得する取得部と、
前記コード列に含まれる前記各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、対応する前記クラス・テストが許可するクラスに前記実行時のクラスを追加することにより前記コード列を最適化する最適化部と、
を含む最適化装置。
【請求項１４】
最適化された前記コード列の実行に対し、前記取得部及び前記最適化部の処理が繰り返される、請求項１３に記載の最適化装置。
【請求項１５】
前記最適化部は、取得したレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求するいずれかの仮想関数の呼び出しを失敗させたことを条件に、該失敗させたレシーバ・オブジェクトの実行時のクラスを対応するクラス・テストに拒絶すべきクラスとして追加する、請求項１４に記載の最適化装置。
【請求項１６】
前記最適化部は、前記クラス・テストにおいて許可すべきクラス又は拒絶すべきクラスの数が所定数を超える場合に当該所定数を超える複数のクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラス又は拒絶すべきクラスとして追加する、請求項１５に記載の最適化装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、コンパイラ最適化技術に関し、より詳細には、記録されたトレース又は特殊化された直線実行パス内のvirtualcall guardを最適化するコンパイラ最適化技術に関する。
【背景技術】
【０００２】
従来、頻繁に実行される直線的な命令列を実行時プロファイルにより見つけてコンパイルを行う、トレースベースのコンパイラが知られている。トレースベースのコンパイラは、ガード付きメソッド展開による最適化と同様に、メソッドの境界において呼び出されるメソッドが一意に定まらない場合に、トレースに記録されているメソッドと実行すべきメソッドとが一致することを実行時に確認するvirtualcall guardと呼ばれるガードを挿入する。上記性質を有するメソッドは、仮想関数（virtualmethod）として知られており、仮想関数は、オブジェクト指向言語の特徴の１つである「多様性（polymorphism）」を実現するための機能である。
【０００３】
ところで上記ガードによる確認には２つの方法が存在する。１つはクラス・テスト(classtest)と呼ばれる方法であり、仮想関数呼び出しにおいて使用されるレシーバ・オブジェクト（実際に呼び出すメソッドを決定するのに用いられるオブジェクト、以下同様）について、トレース記録時のクラスと実行時のクラスとを比較することによってメソッドの一致を確認する方法である（例えば特許文献１及び２を参照）。また１つはメソッド・テスト（methodtest）と呼ばれる方法であり、仮想関数呼び出しにおいて使用されるレシーバ・オブジェクトの実行時のクラスが、インラインされたメソッドを呼び出すクラスであることを確認する方法である。
【０００４】
また、ガード付きメソッド展開による最適化においては、多相的インライン・メソッド・キャッシュ（polymorphicinline cache: PIC）として知られるガード技術が存在する。最も古典的なvirtualcall guardの技術では、仮想関数呼び出しに対して毎回呼び出し先の検索が行われる。そこで呼び出し前にコールサイトにおいて最も頻繁に現れる１のクラスの確認を行うことにより多くの場合に検索を省略するinlinecache(IC)と呼ばれる技術が開発された。PICはこのICを更に拡張した技術であり、呼び出し前にコールサイトにおいて頻繁に現れる複数のクラスのチェックを行う技術である（例えば、非特許文献１を参照）。
【０００５】
更に、オブジェクト・リファレンスをパラメータに取る仮想メソッドをインラインする際に、その仮想メソッドのレシーバ・オブジェクトの型チェックに加えて、パラメータとして渡されるオブジェクトの型チェックをvirtualcall guardに含める技術も存在する（例えば、特許文献３を参照）。
【先行技術文献】
【特許文献】
【０００６】
【特許文献１】米国特許第６１７５９５６号明細書
【特許文献２】米国特許第６１６１２１７号明細書
【特許文献３】米国特許第７７１６６５７号明細書
【非特許文献】
【０００７】
【非特許文献１】Urs Holzle, Craig Chambers,David Ungar , “Optimizing dynamically-typed object-oriented languages withpolymorphic inline caches”, ECOOP ’91 proceedings, Springer Verlag LectureNotes in Computer Science 512, July, 1991
【発明の概要】
【発明が解決しようとする課題】
【０００８】
上述したクラス・テストによる確認方法は、ポインタの比較による確認のためチェックによるオーバーヘッドが小さいという利点、また、一度確認を行えば同じレシーバ・オブジェクトを使用する他の仮想関数呼び出しについてのチェックを省略できるという利点がある。しかしながらクラス・テストによる確認はクラスの一致によりメソッドの一致を確認するものであるため、別のクラスが承継により同じメソッドを呼び出す場合に確認に失敗するという欠点がある。
【０００９】
一方、メソッド・テストによる確認方法は、仮想関数のレシーバ・オブジェクトの実行時のクラスがインラインされた記録時のメソッドを呼び出すことを確認するため、別のクラスが承継により同じメソッドを呼び出す場合に正しくガードを通過させることができる。しかしながらメソッド・テストによる確認方法は、実行時に呼び出し先の解決を必要とするためチェックによるオーバーヘッドが大きく、またクラス・テストのようなチェックの省略ができないという欠点がある。
【００１０】
そこでPICのように、クラス・テストにおいてガードを通過させるクラスを複数設定することが考えられる。しかしながら、コールサイトにおいて頻繁に現れるクラスがトレース記録時のメソッドを呼び出すクラスであるとの保証はないため、単純にPICを適用することはできない。なお、特許文献３の技術は、１の仮想関数呼び出しにおいてチェック対象のオブジェクトが複数ある場合の技術であるため、上記問題に対し何ら解決策を与えない。
【００１１】
この発明は、上記の問題点を解決するためになされたものであって、トレースベースのコンパイラ又はPath specializationを適用するメソッドベースのコンパイラにおいて、メソッドの境界におけるvirtualcall guardのオーバーヘッドを削減し、システムの性能を向上させることを目的とする。また本発明は、従来のクラス・テストの利点を維持しつつ、その欠点をカバーしうる新たなガード技術を提供することを目的とする。
【課題を解決するための手段】
【００１２】
上記課題を解決するために、本発明の１態様によれば、コンピュータ処理により、記録されたトレース又はスペシャライズされた直線実行パス（以下、まとめて「コード列」という）を最適化する第１の最適化方法が提供される。第１の最適化方法は、（ａ）記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対しメソッド・テストを挿入するステップと、（ｂ）前記コード列の実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得するステップと、（ｃ）前記コード列に含まれる前記各仮想関数に対し、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、前記メソッド・テストに代えて、前記対応するレシーバ・オブジェクトの記録時のクラス及び前記実行時クラスを許可すべきクラスとするクラス・テストを挿入することにより、前記コード列を最適化するステップとを含む。
【００１３】
好ましくは、上記ステップ（ｃ）において、許可すべきクラスとするクラス数が所定数を超える場合に複数の許可すべきクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラスとして追加する。
【００１４】
より好ましくは、ステップ（ｃ）において、使用するレシーバ・オブジェクトが同一である複数の仮想関数については、前記コード列内において最初に実行される仮想関数に対してのみ前記クラス・テストを挿入し、残りの仮想関数に対する前記クラス・テストを省略する。
【００１５】
更に好ましくは、前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスは、挿入されたすべての前記メソッド・テストの成功を条件にプロファイルされる。
【００１６】
また、本発明の他の態様によれば、上記コード列を最適化する第２の最適化方法が提供される。第２の最適化方法は、（ａ）記憶装置から前記コード列を読み出し、該コード列に含まれる各仮想関数に対し、該仮想関数の呼び出しに使用されるレシーバ・オブジェクトの記録時のクラスを許可すべきクラスとするクラス・テストと、該クラス・テストの失敗をその実行の条件とするメソッド・テストとを挿入するステップと、（ｂ）挿入処理済みの前記コード列を実行において前記各仮想関数の呼び出しに使用されたレシーバ・オブジェクトのプロファイルされた１以上の実行時のクラスを取得するステップと、（ｃ）前記コード列に含まれる各仮想関数について、対応するレシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対し前記メソッド・テストを要求する全ての仮想関数呼び出しを成功させたことを条件に、対応する前記クラス・テストが許可するクラスに前記実行時のクラスを追加することにより、前記コード列を最適化するステップとを含む。
【００１７】
好ましくは、最適化されたコード列の実行に対してステップ（ｂ）及び（ｃ）が繰り返される。
【００１８】
より好ましくは、ステップ（ｂ）において、各仮想関数に対して挿入された前記メソッド・テストのプロファイルされたテスト結果を合わせて取得し、ステップ（ｃ）において、前記メソッド・テストの結果が失敗であった仮想関数が使用するレシーバ・オブジェクトの実行時のクラスを、対応するクラス・テストに拒絶すべきクラスとして追加する。
【００１９】
更に好ましくは、ステップ（ｃ）において、前記クラス・テストにおいて許可すべきクラス又は拒絶すべきクラス数が所定数を超える場合に当該所定数を超える複数のクラスの中からプロファイル回数の多い上位のクラスのみを許可すべきクラス又は拒絶すべきクラスとして追加する。
【００２０】
以上、最適化方法として本発明を説明したが、本発明は、上記説明した最適化方法の各ステップをコンピュータに実行させるための最適化プログラム、及び該最適化プログラムを１以上のコンピュータにインストールすることにより実現される最適化装置として把握することもできる。
【発明の効果】
【００２１】
本発明によれば、virtualcall guardとしてメソッド・テストを用いたコード列のコンパイル前又はコンパイル後の実行におけるプロファイル結果に基づき、virtualcall guardの通過を許可すべきクラスが決定され、その後のvirtual callguardとしてのクラス・テストにおける許可クラスを複数設定できるので、従来のメソッドの境界におけるvirtual callguardのオーバーヘッドを削減し、システムの性能を向上させることができる。本発明のその他の効果については、各実施の形態の記載から理解される。
【図面の簡単な説明】
【００２２】
【図１】本発明に係る最適化方法を適用可能なコンピュータ・システム５０の機能構成を示す構成図である。
【図２】本発明を実現するソフトウェアの構成を示すブロック図である。
【図３】クラス毎のメソッド定義の一例を示す図である。
【図４】図４（ａ）は、記録されたトレースの一例を示す。図４（ｂ）、（ｃ）、（ｄ）は各々、図４（a）に示すトレースの実行結果の一例を示す図である。
【図５】図４（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する第１の実施形態における最適化処理を説明する図である。
【図６】図６（ａ）は、記録されたトレースの他の例を示す。図６（ｂ）、（ｃ）、（ｄ）は各々、図６（a）に示すトレースの実行結果の一例を示す図である。
【図７】図７（ａ）、（ｂ）は各々、（図６（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する第１の実施形態における最適化処理を説明する図である。
【図８】本発明の第１の実施形態に係る最適化処理全体のフローチャートである。
【図９】図９（ａ）は、記録されたトレースの一例を示す。図９（ｂ）、（ｃ）、（ｄ）は各々、図９（ａ）に示すトレースの実行結果の一例を示す図である。
【図１０】図９（ｂ）、（ｃ）、（ｄ）に示す実行の結果に対する第２の実施形態における最適化処理を説明する図である。
【図１１】図１１（ａ）は、記録されたトレースの一例を示す。図１１（ｂ）、（ｃ）、（ｄ）は各々、図１１（ａ）に示すトレースの実行結果の一例を示す図である。
【図１２】図１１（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する第２の実施形態における最適化処理を説明する図である。
【図１３】図１１（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する第２の実施形態における最適化処理を説明する図である。
【図１４】本発明の第２の実施形態に係る最適化処理全体のフローチャートである。
【図１５】従来技術と本発明（第１の実施形態）とで性能を比較した実験結果を示す図である。
【図１６】従来技術と本発明（第１の実施形態）とでコードサイズを比較した実験結果を示す図である。
【発明を実施するための形態】
【００２３】
以下、本発明を実施するための形態を図面に基づいて詳細に説明するが、以下の実施形態は特許請求の範囲にかかる発明を限定するものではなく、また実施形態の中で説明されている特徴の組み合わせの全てが発明の解決手段に必須であるとは限らない。
【００２４】
図１は、本発明を適用可能なコンピュータ・システム５０の構成を示す。コンピュータ５０は、バス２に接続されたメインCPU（中央処理装置）１とメイン・メモリ４を含んでいる。CPU１は好ましくは、32ビット又は64ビットのアーキテクチャに基づくものであり、例えば、インテル社のCore i（商標）シリーズ、Core 2（商標）シリーズ、Atom（商標）シリーズ、Xeon（商標）シリーズ、Pentium（登録商標）シリーズ、Celeron（登録商標）シリーズ、AMD社のPhenom（商標）シリーズ、Athlon（商標）シリーズ、Turion（商標）シリーズ又はSempron（商標）が使用されうる。メイン・メモリ４は好ましくは、1GB以上の容量、より好ましくは、2GB以上の容量をもつものであってよい。
【００２５】
またハードディスク装置１３、３０、及びCD-ROM装置２６、２９、フレキシブル・ディスク装置２０、MO装置２８、DVD装置３１のようなリムーバブル・ストレージ（記録メディアを交換可能な外部記憶システム）がフレキシブル・ディスクコントローラ１９、IDEコントローラ２５、SCSIコントローラ２７などを経由してバス２へ接続されている。フレキシブル・ディスク、MO、CD-ROM、DCD-ROMのような記憶メディアが、リムーバブル・ストレージに挿入される。
【００２６】
これら記憶メディアやハードディスク装置１３、３０、ROM１４には、オペレーティング・システム、J2EEなどの処理環境、アプリケーション、仮想マシン（VM）、実行時（JIT）コンパイラを提供するプログラム、その他のプログラム及びデータが、メイン・メモリ４にロード可能に記憶されてよい。なお、オペレーティング・システムは、Linux（商標）、マイクロソフト社のWindows（商標）7、Windows XP（商標）、Windows（商標）2003サーバ、アップルコンピュータ社のMac OS（商標）などの、CPU１に適合する任意のものでよい。
【００２７】
更に、上記記憶メディアやハードディスク装置１３、３０、ROM１４には、オペレーティング・システムと協働してCPU１に命令を与え、本発明を実施するためのコンピュータ・プログラムを記録することができる。即ち、上記説明した数々の記憶装置には、コンピュータ・システム５０にインストールされ、コンピュータ・システム５０を本発明の実施形態による最適化装置として機能させる最適化プログラムや各種データを記録することができる。
【００２８】
上記最適化プログラムは、挿入モジュールと、取得モジュールと、最適化モジュールとを含む。これらプログラム及びモジュールは、CPU１に働きかけて、コンピュータ・システム５０を、各々後述する挿入部２１２と、取得部２１４と、最適化部２１８としてそれぞれ機能させる。なお、これら機能はトレースベースのJITコンパイラ又はPathspecializationを適用するメソッドベースのJITコンパイラの機能の一部として実装されてよい。コンピュータ・プログラムは圧縮し、また複数に分割して複数の媒体に記録することもできる。  
【００２９】
コンピュータ・システム５０は、キーボード／マウス・コントローラ５を経由して、キーボード６やマウス７のような入力デバイスからの入力を受ける。コンピュータ・システム５０は、オーディオコントローラ２１を経由して、マイク２４からの入力を受け、またスピーカー２３から音声を出力する。コンピュータ５０は、視覚データをユーザに提示するための表示装置１１に、グラフィックスコントローラ１０を経由して接続される。コンピュータ・システム５０は、ネットワーク・アダプタ１８（イーサネット（登録商標）・カードやトークンリング・カード）等を介してネットワークに接続し、他のコンピュータ等と通信を行うことが可能である。
【００３０】
以上の説明により、コンピュータ・システム５０は、通常のパーソナルコンピュータ、ワークステーション、メインフレームなどの情報処理装置、又は、これらの組み合わせによって実現されることが容易に理解されるであろう。なお、上記説明した構成要素は例示であり、そのすべての構成要素が本発明の必須構成要素となるわけではない。
【００３１】
図２は、本発明を実現するソフトウェアの構成を示すブロック図である。同図において、オペレーティング・システム２０２は、CPUやメモリを資源として管理し、時分割によるマルチスレッドの機能を実現する。仮想マシン２０４は、実行対象のプログラムの一部である記録されたトレース又は特化された直線実行パス（以下、まとめて「コード列」という）２０６とオペレーティング・システム２０２とのインタフェースを行うソフトウェアであり、コード列２０６から見て仮想マシン２０４以下の階層全体を例えばJava（登録商標）仮想マシン（Virtual  Machine）として作用させる。なお、以下の説明では仮想マシン２０４はJava（登録商標）仮想マシン（Virtual  Machine）であるとして説明する。
【００３２】
仮想マシン２０４は、バイトコードを実行時に動的に機械語にコンパイルしてネイティブコードを生成し、プログラムの実行を高速化するコンパイラ２０８Ａ／Ｂと、プログラムがバイトコード等の中間コードで与えられるときこれを解釈する実行部（インタープリタ）２２０と、その解釈に応じて呼び出されるプロファイラ２２２Ａ／Ｂとを含む。なお、コンパイラ２０８とプロファイラ２２２に付されるＡ／Ｂの符号は、Ａが後述する本発明の第１実施形態に係るコンパイラ２０８及びプロファイラ２２２であることを、また、Ｂが後述する本発明の第２実施形態に係るコンパイラ２０８及びプロファイラ２２２であることを示している。以後使用するＡ／Ｂの符号も同様の意味を有するものとする。ここで、コンパイラ２０８Ａ／Ｂは、コンパイル単位をトレースとするトレースベースのJITコンパイラ、又はコンパイル単位をメソッドとするメソッドベースのコンパイラである。但し後者の場合メソッドベースのコンパイラはPath specializationを適用するものとする。更に本発明の第１の実施形態に係るコンパイラ２０８Ａは、たとえばＣ＋＋のコンパイラ等、静的コンパイルを行うコンパイラであってもよい。また、以下ではプロファイル用のコードはコンパイラ２０８Ａ／Ｂにより挿入されるものとして説明するが、これに限定されず、プロファイラ２２２Ａ／Ｂの機能を実行部２２０に実装してもよい。
【００３３】
そしてコンパイラ２０８Ａ／Ｂは、コード列２０６に含まれる仮想関数の呼び出しに対するvirtual callguardを最適化する最適化装置２１０Ａ／Ｂを含む。最適化装置２１０Ａ／Ｂは、virtualcall guardであるメソッド・テストのチェック結果を利用して、virtual callguardであるクラス・テストにおける許可クラスに複数のクラスを設定する。
【００３４】
ここでメソッド・テストとは、背景技術で説明した通り、仮想関数の呼び出しにおいて使用されるレシーバ・オブジェクトの実行時のクラスが、記録時のインラインされたメソッドを呼び出すことを確認する方法である。より具体的には、レシーバ・オブジェクトの実行時のクラスを出発点に、該クラスのメソッド・テーブルを辿り、メソッド・テーブルから呼び出すべきメソッドのアドレスを取得して、取得したアドレスがインラインされたメソッドのアドレスと同一であることを確認する方法である。
【００３５】
クラス・テストもまた、背景技術で説明した通り、仮想関数呼び出しにおいて使用されるレシーバ・オブジェクトについて、トレース記録時のクラスと実行時のクラスとを比較することによってメソッドの一致を確認する方法である。より具体的には、レシーバ・オブジェクトの実行時のクラスを指すポインタとトレース記録時のクラスを指すポインタとを比較して、同一であることを確認する方法である。
なお、メソッド・テスト及びクラス・テストそれ自体は、どちらも既存の技術であるためこれ以上の説明は省略する。
【００３６】
メソッド・テストを利用したvirtual call guardの通過を許可すべきクラスの決定は、コンパイル前の実行におけるプロファイリングの結果に基づいて行ってもよく、又はコンパイル後の実行におけるプロファイリングの結果に基づいて繰り返し行い、その都度許可すべきクラスを追加してもよい。以下では、前者を第１実施形態、後者を第２実施形態として順に説明する。
【００３７】
（第１実施形態）
このセクションでは、virtual callguardとしてメソッド・テストを挿入したコード列２０６のコンパイル前の実行におけるプロファイリング結果に基づいてvirtual callguardの通過を許可すべきクラスを決定し、挿入したメソッド・テストを、複数のクラスを許可クラスとするクラス・メソッドで置換することによりvirtualcall guardを最適化する手法について説明する。なお、コンパイラ２０８Ａによるコンパイルはvirtualcall guardを最適化されたコード列２０６に対して行われることに留意されたい。図２に示すように、第１実施形態に係る最適化装置２１０Ａは、挿入部２１２Ａと、取得部２１４Ａと、最適化部２１８Ａとを含む。
【００３８】
挿入部２１２Ａは、次にコンパイル対象とするコード列２０６を読み出して走査し、コード列２０６に含まれる各仮想関数に対しvirtualcall guardとしてメソッド・テストを挿入する。メソッド・テストの挿入位置はメソッド境界とする。但し、レシーバ・オブジェクトのクラスが先頭位置で決まっていることが確認できる場合は、挿入位置はコード列２０６の先頭であってもよい。また、仮想関数の呼び出しに使用するレシーバ・オブジェクトが同一である複数の仮想関数については、挿入するメソッド・テストをまとめて１つとしてよい。但し挿入するメソッド・テストは、使用されるレシーバ・オブジェクトの実行時のクラスが、上記複数の仮想関数すべてを呼び出すクラスであることを確認するものとする。また、メソッド・テストの挿入位置は、上記複数の仮想関数のうち、コード列２０６において最初に実行される仮想関数の直前とする。
【００３９】
挿入部２１２Ａはまた、挿入されたすべてのメソッド・テストの成功を条件として各仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスを記録するコードを挿入する。一例として挿入部２１２Ａは、各レシーバ・オブジェクトの実行時のクラスをプロファイルするコード（以下、「プロファイラＡ」と呼ぶ）をコード列２０６の末尾に挿入する。但し、プロファイラＡのコードが非常に長くなるような場合は、プロファイラＡを呼び出すコードをコード列２０６の末尾に挿入するのが好ましい。なお、コード列２０６の実行はメソッド・テストが失敗した時点で終了するものとする。これに代えて、挿入部２１２Ａは、上述したように、使用するレシーバ・オブジェクトが同一である複数の仮想関数については挿入するメソッド・テストを１つにまとめ、かつ、メソッド・テストごと、仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスとメソッド・テストのテスト結果（成功／失敗）とをプロファイルするコードを挿入してもよい。前者の場合、プロファイル結果に基づき決定できるのはvirtualcall guardの通過を許可すべきクラスである。一方、後者の場合、プロファイル結果に基づき決定できるのは、virtualcall guardの通過を許可すべきクラスと拒絶すべきクラスである。なお、本実施例では前者の構成を採用するものとする。後者の詳細については第２実施形態に関連して後述する。挿入部２１２Ａはまた、プロファイル結果を格納するためのプロファイル・テーブルを作成する。プロファイル・テーブルの詳細は図８を参照して後述する。メソッド・テストを挿入されたコード列２０６はその後、プロファイル結果を取得するため実行部２２０により繰り返し実行される。
【００４０】
取得部２１４Ａは、プロファイラＡにより記録されたプロファイル結果２２４Ａを読み出し、コード列２０６に含まれる各仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスを取得する。取得部２１４Ａは、取得した各レシーバ・オブジェクトの実行時のクラスを最適化部２１８Ａに渡す。
【００４１】
最適化部２１８Ａは、取得部２１４Ａから受け取った各レシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトに対しメソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、コード列２０６に挿入されているメソッド・テストをクラス・テストで置換する。その際最適化部２１８Ａは、各クラス・テストについて、対応するレシーバ・オブジェクトのコード列２０６記録時におけるクラスに加えて該レシーバ・オブジェクトに対してプロファイルされた実行時のクラスを許可すべきクラスとして設定する。    
【００４２】
なお、各レシーバ・オブジェクトの実行時のクラスは、上述したようにコード列２０６に挿入されたすべてのメソッド・テストが成功した場合にのみ記録され、プロファイルされる。そのため、最適化部２１８Ａは、取得部２１４Ａから各レシーバ・オブジェクトの実行時のクラスを受け取ることができた場合には、上記条件が満たされていることを確認することなくそのまま上記置換処理を行ってよい。
【００４３】
最適化部２１８Ａはまた、１のレシーバ・オブジェクトに対してプロファイルされた実行時のクラスが所定数を超える場合は、その複数のプロファイルされた実行時のクラスの中からプロファイル回数の多い上位m個（mは１以上の整数）のクラスのみを許可すべきクラスとして設定するのが好ましい。そのためにプロファイラＡは、レシーバ・オブジェクトの実行時のクラス情報と共にそのプロファイル回数も合わせて記録するものとする。クラス・テストにおいて許可されるクラスの数が非常に多くなるとチェックのコストが大きくなり得る。そこで、上記構成を採用することによってコスト増を避けつつも性能向上を図ることが可能となる。
【００４４】
最適化部２１８Ａはまた、レシーバ・オブジェクトが同一である複数の仮想関数呼び出しについては、最初に実行される仮想関数呼び出しに対してのみクラス・テストを挿入し、残りの仮想関数呼び出しに対しては挿入済みのメソッド・テストは削除するだけで、クラス・テストを省略するのが好ましい。これによってコードサイズを小さくすることが可能となる。最適化部２１８Ａによる処理が済んだコード列２０６はその後コンパイラ２０８Ａにより機械語にコンパイルされる。
【００４５】
次に、図３〜図５を参照して、プロファイル結果に基づいてvirtualcall guardを最適化する第１の実施形態に係る最適化方法を具体的に説明する。図３は、クラス毎のメソッド定義の一例を示す図である。図４（ａ）は、記録されたトレースの一例を示す。図４（ｂ）、（ｃ）、（ｄ）は各々、図４（ａ）に示すトレースの実行結果の一例を示す図である。図５は、図４（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する最適化処理を説明する図である。
【００４６】
本実施例では、図３に示すように、methodAとmethodBをメンバとしてもつsuperClassを拡張して、childClass0、1、2が作成されたとする。ここで、childClass0はmethodAとmethodBの両方をそのまま承継するが、childClass1はmethodAをオーバーライドしたmethodA’と、methodBをメンバとしてもち、childClass2はmethodA と、methodBをオーバーライドしたmethodB’と をメンバとしてもつとする。
【００４７】
またトレース４００は、図４（ａ）に示すように、２つの仮想関数呼び出しcallobj.methodAとcall obj.methodBを含む。仮想関数の呼び出しに使用されるレシーバ・オブジェクトobjは、トレース４００の記録時にsuperClassのインスタンスであったため、記録されたトレース４００では、これら２つの仮想関数呼び出しに対し、それぞれsuperClassのメンバmethodA()とmethodB()とがインラインされている。挿入部２１２Aはコンパイル対象としてトレース４００を読み込むと、２つの仮想関数それぞれに対し、virtualcall guard４０２、４０４としてメソッド・テストを挿入する。挿入されるメソッド・テストは、テストが成功した場合は実行を継続させ、失敗した場合は実行を終了させるテストである。挿入部２１２Aはまた、トレース４００の末尾にプロファイラＡを直接またはプロファイラＡを呼び出すコードを挿入する。
【００４８】
図４（ｂ）、（ｃ）、（ｄ）は、上記説明した状況においてプロファイル結果を取得するために実行部２２０がトレース４００を実行した結果を示す。図４（ｂ）に示す実行結果４１０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass0である。上述したようにchildClass0は、methodAとmethodBの両方をそのまま承継しているので、メソッド・テストは、図４（ａ）に示すvirtualcall guard４０２に対応する地点４１２及びvirtual callguard４０４に対応する地点４１４の両地点において成功している。結果、プロファイラＡによりレシーバ・オブジェクトobjの実行時のクラスとしてchildClass0が記録される。
【００４９】
図４（ｃ）に示す実行結果４２０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass1である。上述したようにchildClass1は、methodAをオーバーライドしている。そのため、メソッド・テストは図４（a）に示すvirtual call guard４０２に対応する地点４２２において失敗している。結果、トレース４００の実行は途中で終了し、プロファイラＡは実行されないため、レシーバ・オブジェクトobjの実行時のクラスchildClass1も記録されない。
【００５０】
また、図４（ｄ）に示す実行結果４３０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass2である。上述したようにchildClass2は、methodA についてはそのまま承継しているが、methodBについてはオーバーライドしている。そのため、メソッド・テストは図４（a）に示すvirtual call guard４０２に対応する地点４３２において成功しているものの、virtualcall guard４０４に対応する地点４３４において失敗している。結果、トレース４００の実行は途中で終了し、プロファイラＡは実行されないため、レシーバ・オブジェクトobjの実行時のクラスchildClass2も記録されない。
【００５１】
図４（b）、（c）、（d）に示す実行結果に対し、取得部２１４Ａはプロファイル結果としてchildClass0を取得する。最適化部２１８Ａは取得部２１４ＡからchildClass0を受け取ると、これを用いてトレース４００に含まれるvirtualcall guard４０２、４０４を最適化する。図５は、最適化されたvirtualcall guard４０２、４０４を示す。図５に示すように、メソッド・テストと置換されたクラス・テストは、トレース４００記録時のレシーバ・オブジェクトobjのクラスであるsuperClassと、プロファイルされた実行時のクラスであるchildClass0とを許可クラスとする。なお、virtual call guard４０２、４０４はいずれも同じレシーバ・オブジェクトobjを使用する仮想関数の呼び出しに対するものであるため、後に実行されるvirtual callguard４０４としてのクラス・テストは省略してよい。
【００５２】
図４〜図５を参照して説明した例では、トレース４００内で使用されるレシーバ・オブジェクトは１つのみであった。そこで次に図６及び図７を参照して、トレース内で使用されるレシーバ・オブジェクトが２つである場合について説明する。図６（a）は、記録されたトレースの他の例を示す。図６（b）、（c）、（d）は各々、図６（a）に示すトレースの実行結果の一例を示す。図７は、図６（b）、（c）、（d）に示す実行結果に対する最適化処理を説明する図である。なお、クラス毎のメソッドの定義状況は図３を参照して説明した通りである。
【００５３】
図６（a）に示すトレース６００は、２つの仮想関数呼び出しcallobjX.methodAとcall objY.methodBを含む。仮想関数の呼び出しに使用されるレシーバ・オブジェクトobjXとobjYは、トレース６００の記録時に共にsuperClassのインスタンスであったため、記録されたトレース６００では、これら２つの仮想関数呼び出しに対しsuperClassのメンバmethodA()とmethodB()がそれぞれインラインされている。挿入部２１２Aはコンパイル対象としてトレース６００を読み込むと、２つの仮想関数呼び出しそれぞれに対し、virtualcall guard６０２、６０４としてメソッド・テストを挿入する。挿入されるメソッド・テストは、テストが成功した場合は実行を継続させ、失敗した場合は実行を終了させるテストである。挿入部２１２Aはまた、トレース６００の末尾にプロファイラＡを直接またはプロファイラＡを呼び出すコードを挿入する。
【００５４】
図６（b）、（c）、（d）は、上記説明した状況においてプロファイル結果を取得するために実行部２２０がトレース６００を実行した結果を示す。図６（ｂ）に示す実行結果６１０では、レシーバ・オブジェクトobjXの実行時のクラスはchildClass2であり、レシーバ・オブジェクトobjYの実行時のクラスはchildClass1である。図３に示したようにクラスchildClass2は、methodAをそのまま承継しているので、図６（a）に示すvirtual call guard６０２に対応する地点６１２においてメソッド・テストは成功している。同様に、クラスchildClass1も、methodBをそのまま承継しているので、図６（a）に示すvirtual call guard６０４に対応する地点６１４においてメソッド・テストは成功している。結果、プロファイラＡにより、レシーバ・オブジェクトobjXの実行時のクラスとしてchildClass2が、objYの実行時のクラスとしてchildClass1がそれぞれ記録される。
【００５５】
図６（ｃ）に示す実行結果６２０では、レシーバ・オブジェクトobjXとobjYの実行時のクラスは共にchildClass0である。上述したようにchildClass0は、methodAとmethodBをそのまま承継しているので、メソッド・テストは図６（a）に示すvirtual call guard６０２に対応する地点６２２とvirtualcall guard６０４に対応する地点６２４の両地点において成功している。結果、プロファイラＡにより、レシーバ・オブジェクトobjXとobjYの実行時のクラスとして共にchildClass0が記録される。
【００５６】
図６（ｄ）に示す実行結果６３０では、レシーバ・オブジェクトobjXとobjYの実行時のクラスは共にchildClass2である。上述したようにchildClass2は、methodAについてはそのまま承継しているが、methodBについてはオーバーライドしている。そのため、メソッド・テストは図６（a）に示すvirtual call guard６０４に対応する地点６３２では成功するが、virtualcall guard６０４に対応する地点６３４では失敗している。結果、トレース４００の実行は途中で終了し、プロファイラＡは実行されないため、レシーバ・オブジェクトobjXとobjYの実行時のクラスchildClass2も記録されない。
【００５７】
図６（b）、（c）、（d）に示す実行結果に対し、取得部２１４Aはプロファイル結果としてレシーバ・オブジェクトobjX に対しchildClass2とchildClass0の２つのクラスを、レシーバ・オブジェクトobjYに対しchildClass1とchildClass0の２つのクラスをそれぞれ取得する。最適化部２１８Ａは取得部２１４Aからプロファイル結果を受け取ると、これを用いてトレース６００に含まれるvirtualcall guard６０２、６０４を最適化する。図７(a) は最適化されたvirtual callguard６０２を、図７（b）は、最適化されたvirtual callguard６０４をそれぞれ示す。図７(a)に示すように、メソッド・テストと置換されたvirtual callguard６０２としてのクラス・テストは、トレース６００記録時のレシーバ・オブジェクトobjXのクラスであるsuperClassに加えて、プロファイルされた実行時のクラスであるchildClass2とchildClass0とを許可クラスとする。また、図７(b)に示すように、メソッド・テストと置換されたvirtualcall guard６０４としてのクラス・テストは、トレース６００記録時のレシーバ・オブジェクトobjYのクラスであるsuperClassに加えて、プロファイルされた実行時のクラスであるchildClass1とchildClass0とを許可クラスとする。なお、virtualcall guard６０２、６０４はそれぞれ異なるレシーバ・オブジェクトobjX、objYを使用する仮想関数の呼び出しに対するものであるため、後に実行されるvirtualcall guard６０４としてのメソッド・テストを省略することはできない。  
【００５８】
次に図８を参照して、本発明の第１の実施形態に係る最適化装置２１０Ａによる処理の流れを説明する。図８に示す処理は、ステップ８００より開始され、最適化装置２１０Ａは、プロファイル結果を格納するための空のプロファイル・テーブル８２２を作成する。作成するプロファイル・テーブル８２２は、レシーバ・オブジェクトのフィールドと、実行時クラスのフィールドと、回数のフィールドとを有する。レシーバ・オブジェクトのフィールドのエントリには、プロファイル対象のレシーバ・オブジェクトの名前が格納される。実行時クラスのフィールドのエントリには、プロファイル対象のレシーバ・オブジェクトの実行時のクラスが格納される。回数のフィールドのエントリには、該エントリと同一の内容がプロファイルされた回数が格納される。
【００５９】
続いて最適化装置２１０Ａは、コード列格納部８２４から次にコンパイル対象とするコード列２０６を読み出し、読み出したコード列２０６に含まれる各仮想関数に対しメソッド・テストを挿入する（ステップ８０２）。最適化装置２１０Ａはまた、挿入した全メソッド・テストの成功を条件に、各仮想関数の呼び出しに使用されるレシーバ・オブジェクトの実行時のクラスと、プロファイル回数を記録するコードを挿入する（ステップ８０２）。
【００６０】
ここで挿入されるコードは実行されると次のように動作する。即ち、コード列２０６に含まれるレシーバ・オブジェクトごと、該レシーバ・オブジェクトの名前とその現在のクラスをキーとしてプロファイル・テーブル８２２を検索する。マッチするエントリが存在する場合、そのエントリの回数フィールドの値を１増加する。マッチするエントリが存在しない場合、レシーバ・オブジェクトのフィールドを現在のレシーバ・オブジェクトの名前、実行時クラスのフィールドをレシーバ・オブジェクトの現在のクラス、回数のフィールドを値１とするエントリを新たに追加する。挿入処理済のコード列２０６はその後コード列格納部８２４に戻される。
【００６１】
続いて最適化装置２１０Ａは、挿入処理済のコード列２０６の実行を実行部２２０に要求し（ステップ８０４）、プロファイル結果の取得を試みる（ステップ８０６）。なお、実行部２２０による実行は予め定めた回数行われるものとする。最適化装置２１０Ａは、プロファイル結果を取得できたか否かを判定し（ステップ８０８）、プロファイル結果を取得できなかった場合（ステップ８０８：NO）、ステップ８０４に戻って再度コード列２０６の実行を要求する。
【００６２】
一方、プロファイル結果を取得できた場合（ステップ８０８：YES）、最適化装置２１０Ａは、コード列２０６に含まれるレシーバ・オブジェクトごと、プロファイル・テーブル８２２から回数の多い上位ｍ個（ｍは１以上の整数）のエントリを選択し、選択した各エントリの実行時クラスとコード列２０６記録時のクラスとを許可クラスとするクラス・テストのコードを生成し、コード列２０６内の対応するメソッド・テストと置換する（ステップ８１０）。なお、同一のレシーバ・オブジェクトに関するメソッド・テストがコード列２０６内に複数に含まれる場合、コード列２０６内において最初に実行されるメソッド・テストのみを上記生成したクラス・テストと置換し、残りのメソッド・テストは削除してよい。複数のクラスの通過を許可するクラス・テストによってvirtualcall guardを最適化されたコード列２０６はその後、最適化済みコード列格納部８２６に格納され、コンパイラ２０８Ａによるコンパイル対象となる。そして処理は終了する。
【００６３】
（第２実施形態）
このセクションでは、virtual callguardとしてクラス・テストと該クラス・テストの失敗をその実行の条件とするメソッド・テストとを挿入したコード列２０６の実行におけるプロファイリング結果に基づいてvirtual callguardの通過を許可すべきクラスを決定し、許可すべきクラスが新たに見つかるごとにこれをクラス・テストの許可クラスに追加してvirtualcall guardを最適化する手法について説明する。なお、コンパイラ２０８Ｂによるコンパイルは許可クラスが追加されるごとに行っても、或いは許可クラスが追加されるごとには行わないようにしてもよい。図２に示すように、第２の実施形態に係る最適化装置２１０Ｂは、挿入部２１２Ｂと、取得部２１４Ｂと、最適化部２１８Ｂとを含む。
【００６４】
挿入部２１２Ｂは、次にコンパイル対象とするコード列２０６を読み出して走査し、コード列２０６に含まれる各仮想関数に対しvirtualcall guardとして、クラス・テストと該クラス・テストの失敗をその実行の条件とするメソッド・テスト（以下、両テストを合わせて「型テスト」という）とを挿入する。ここで挿入する各クラス・テストに対し設定する通過を許可する許可クラスは、対応するレシーバ・オブジェクトのコード列２０６記録時のクラスである。型テストの挿入位置はメソッド境界とする。但し、レシーバ・オブジェクトのクラスが先頭位置で決まっていることが確認できる場合は、挿入位置はコード列２０６の先頭であってもよい。また、仮想関数の呼び出しに使用するレシーバ・オブジェクトが同一である複数の仮想関数については、挿入する型テストをまとめて１つとしてよい。但し挿入する型テストのうちメソッド・テストの部分については、使用されるレシーバ・オブジェクトの実行時のクラスが、上記複数の仮想関数すべてを呼び出すクラスであることを確認するものとする。確認に使用するため挿入部２１２Ｂは、コード列２０６に含まれるすべての仮想関数について仮想関数と該仮想関数の呼び出しに使用するレシーバ・オブジェクトとの組をリストするリストを作成する。また、型テストの挿入位置は、上記複数の仮想関数のうち、コード列２０６において最初に実行される仮想関数よりも前とする。
【００６５】
挿入部２１２Ｂはまた、すべての型テストの成功を条件として各仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスを記録するためのコードを挿入する。一例として挿入部２１２Ｂは、各レシーバ・オブジェクトの実行時のクラスをプロファイルするコードをコード列２０６の末尾に挿入する。但し、コード列２０６の実行はメソッド・テストが失敗した時点で終了するものとする。これに代えて、挿入部２１２Ｂは、上述したように、使用するレシーバ・オブジェクトが同一である複数の仮想関数については挿入する型テストを１つにまとめ、かつ、型テストごと、メソッド・テストの実行を条件に、仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスとメソッド・テストのテスト結果（成功／失敗）とをプロファイルするコード（以下、「プロファイラＢ」と呼ぶ）を挿入してもよい。但し、プロファイラＢのコードが非常に長くなるような場合は、プロファイラＢを呼び出すコードをコード列２０６の末尾に挿入するのが好ましい。メソッド・テストのテスト結果を合わせてプロファイルすることで、プロファイル結果に基づきvirtualcall guardの通過を許可すべきクラスと拒絶すべきクラスの両方を決定できる。そこで本実施例では当該構成について説明する。挿入部２１２Ｂはまた、プロファイル結果を格納するためのプロファイル・テーブルを作成する。プロファイル・テーブルの詳細は図１４を参照して後述する。挿入部２１２Ｂによる処理がなされたコード列２０６はその後、実行部２２０、又はコンパイラ２０８Ｂによりコンパイルされた場合にはＣＰＵ１により実行される。
【００６６】
取得部２１４Ｂは、挿入処理済のコード列２０６の実行においてプロファイラＢにより記録されたプロファイル結果２２４Ｂを読み出し、コード列２０６に含まれる各レシーバ・オブジェクトについて、記録されていれば、実行時のクラスとメソッド・テストのテスト結果とを取得する。取得部２１４Ｂは、取得したレシーバ・オブジェクトごとの実行時のクラスと対応するテスト結果を最適化部２１８Ｂに渡す。
【００６７】
最適化部２１８Ｂは、取得部２１４Ｂから受け取った各レシーバ・オブジェクトの実行時のクラスごとに、該実行時のクラスがレシーバ・オブジェクトに対しメソッド・テストを要求する全ての仮想関数の呼び出しを成功させたことを条件に、コード列２０６に挿入された対応するクラス・テスト、即ち、上記レシーバ・オブジェクトを使用する各仮想関数に対するクラス・テストが許可すべきクラスに上記実行時のクラスを追加する。なお、上述したように本実施例において挿入されるメソッド・テストは、レシーバ・オブジェクトの実行時のクラスが、該レシーバ・オブジェクトを使用するすべての仮想関数を呼び出すクラスであることを確認するものである。従って最適化部２１８Ｂは上記条件が満たされることを対応するテスト結果に従って判断する。
【００６８】
最適化部２１８Ｂはまた、取得部２１４Ｂから受け取った各レシーバ・オブジェクトの実行時のクラスごとに、該実行時のクラスがレシーバ・オブジェクトに対しメソッド・テストを要求するいずれかの仮想関数の呼び出しを失敗させたことを条件に、コード列２０６に挿入された対応する各クラス・テスト、即ち、上記レシーバ・オブジェクトを使用する各仮想関数に対するクラス・テストが拒絶すべきクラスに上記実行時のクラスを追加する。許可すべきクラスの追加に関して説明したのと同様の理由により、最適化部２１８Ｂは上記条件が満たされることを対応するテスト結果に従って判断する。
【００６９】
最適化部２１８Ｂはまた、いずれかのクラス・テストについて許可すべきクラス又は拒絶すべきクラスの数が所定数を超える場合に、当該所定数を超える複数のクラスの中からプロファイル回数の多い上位のｍ個（ｍは１以上の整数）のクラスのみを許可すべきクラス又は拒絶すべきクラスとして追加してよい。この場合、プロファイラ２２２Ｂは、実行時のクラスとテスト結果と共にそのプロファイル回数も合わせて記録するものとする。上述したように、クラス・テストにおいて許可される又は拒絶されるクラスの数が非常に多くなるとチェックのコストが大きくなり得る。そこで、上記構成を採用することによってコスト増を避けつつも性能向上を図ることが可能となる。
【００７０】
最適化部２１８Ｂによる処理が済んだコード列２０６はその後、実行部２２０、又はコンパイラ２０８Ｂによりコンパイルされた場合にはＣＰＵ１により実行される。そして該実行においてプロファイラ２２２Ｂにより得られたプロファイル結果に基づいて、取得部２１４Ｂ及び最適化部２１８Ｂによる上記処理が繰り返される。
【００７１】
次に、図３、図９及び図１０を参照して、プロファイル結果に基づいてvirtual callguardを最適化する第２の実施形態に係る最適化方法を具体的に説明する。図３は、上述したとおりクラス毎のメソッド定義の一例を示す図である。図９（ａ）は、記録されたトレースの一例を示す。図９（ｂ）、（ｃ）、（ｄ）は各々、図９（ａ）に示すトレースを実行した際の実行結果の一例を示す図である。図１０は、図９（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する第２の実施形態における最適化処理を説明する図である。
【００７２】
図３については、第１の実施形態に係る最適化方法に関連して説明した通りである。図９（a）に示すトレース９００は、２つの仮想関数呼び出しcall obj.methodAとcall obj.methodBを含む。仮想関数の呼び出しに使用されるレシーバ・オブジェクトobjは、トレース９００の記録時にsuperClassのインスタンスであったため、記録されたトレース９００では、これら２つの仮想関数呼び出しに対し、それぞれsuperClassのメンバmethodA()とmethodB()とがインラインされている。挿入部２１２Ｂはトレース９００を読み込むと、トレース９００に含まれるすべての仮想関数について仮想関数と該仮想関数の呼び出しに使用するレシーバ・オブジェクトとの組をリストするリスト{（obj, methodA）,(obj,methodB)}を作成する。そして挿入部２１Ｂは、２つの仮想関数の呼び出しに使用されるレシーバ・オブジェクトが共通であることから型テストを１つにまとめ、先に実行される仮想関数に対してのみ、virtualcall guard９０２を挿入する。挿入するvirtual callguard９０２は、superClassをレシーバ・オブジェクトobjの許可クラスとするクラス・テストと該クラス・テストの失敗をその実行の条件とするメソッド・テストである。ここでメソッド・テストは、リストを参照してレシーバ・オブジェクトobjの現在のクラスがレシーバ・オブジェクトobjとの組をリストされる全仮想関数を呼び出すクラスであるか否かをテストし、テストが成功した場合は実行を継続させ、失敗した場合は実行を終了させるテストである。挿入部２１２Ｂはまた、挿入したメソッド・テストに対しプロファイラＢを挿入する。図１０に示すコード１０００は挿入部２１２Ｂにより挿入されるコードの一例である。
【００７３】
図９（ｂ）、（ｃ）、（ｄ）は、図３に示すクラス毎のメソッド定義状況下においてトレース９００を実行した際の実行結果を示す。図９（ｂ）に示す実行結果９１０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass0であり、トレース記録時のクラスsuperClassとは異なるため、トレース９００にvirtual call guard９０２として挿入されたメソッド・テストが実行されている。そしてchildClass0は、methodAとmethodBの両方をそのまま承継しているので、メソッド・テストは成功している。メソッド・テストが実行されることから、プロファイラＢが実行され、レシーバ・オブジェクトobjの実行時のクラスとしてchildClass0とメソッド・テストの結果（成功）が記録される。
【００７４】
図９（ｂ）に示す実行結果９１０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjの実行時のクラスchildClass0についてのメソッド・テストのテスト結果が成功であることから、上記挿入処理済のトレース９００に含まれる対応するクラス・テストの許可クラスにクラスchildClass0を追加する。図１０に示すコード１００２は、クラス・テストの許可クラスにプロファイルされた実行時のクラスchildClass0（参照番号１００４）を追加することによって最適化されたvirtual call guard９０２を示す。
【００７５】
図９（ｃ）に示す実行結果９２０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass1であり、トレース記録時のクラスsuperClassとは異なるため、記録されたトレース９００に挿入されたメソッド・テストが実行されている。そしてchildClass1は、methodAをオーバーライドしているので、メソッド・テストは失敗している。メソッド・テストが実行されたことからプロファイラＢが実行され、レシーバ・オブジェクトobjの実行時のクラスとしてchildClass1とメソッド・テストの結果（失敗）が記録される。なお、メソッド・テストが失敗することにより、プロファイラＢによる処理が終了するとトレース９００の実行が終了することに留意されたい。  
【００７６】
図９（ｃ）に示す実行結果９２０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjの実行時のクラスchildClass1についてのメソッド・テストのテスト結果が失敗であることから、上記最適化処理済のトレース９００に含まれる対応するクラス・テストにクラスchildClass1を設定した拒絶クラスを新たに追加する。図１０に示すコード１００６は、クラス・テストにプロファイルされた実行時のクラスchildClass1を設定した拒絶クラスを追加する（参照番号１００８）ことによって最適化されたvirtual callguard９０２を示す。
【００７７】
図９（ｄ）に示す実行結果９３０では、レシーバ・オブジェクトobjの実行時のクラスはchildClass2であり、トレース記録時のクラスsuperClassとは異なるため、記録されたトレース９００に挿入されたメソッド・テストが実行されている。そしてchildClass2は、methodAについてはそのまま承継しているが、methodBについてはオーバーライドしているので、メソッド・テストは失敗している。メソッド・テストが実行されることからプロファイラＢが実行され、レシーバ・オブジェクトobjの実行時のクラスとしてchildClass2とメソッド・テストの結果（失敗）が記録される。
【００７８】
図９（ｄ）に示す実行結果９３０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjの実行時のクラスchildClass2
についてのメソッド・テストのテスト結果が失敗であることから、上記最適化処理済のトレース９００に含まれる対応するクラス・テストの拒絶クラスにクラスchildClass2を追加する。図１０に示すコード１０１０は、クラス・テストの拒絶クラスにプロファイルされた実行時のクラスchildClass2（参照番号１０１２）を追加することによって最適化されたvirtual call guard９０２を示す。
【００７９】
図３、図９及び図１０参照して説明した例では、トレース９００内で使用されるレシーバ・オブジェクトは１つのみであった。そこで次に図１１から図１３を参照して、トレース内で使用されるレシーバ・オブジェクトが２つである場合について説明する。図１１（ａ）は、記録されたトレースの他の例を示す。図１１（ｂ）、（ｃ）、（ｄ）は各々、図１１（ａ）に示すトレースの実行結果の一例を示す。図１２及び図１３は、図１１（ｂ）、（ｃ）、（ｄ）に示す実行結果に対する最適化処理を説明する図である。なお、クラス毎のメソッドの定義状況は図３を参照して説明した通りである。
【００８０】
図１１（ａ）に示すトレース１１００は、２つの仮想関数呼び出しcallobjX.methodAとcall objY.methodBを含む。仮想関数の呼び出しに使用されるレシーバ・オブジェクトobjXとobjYは、トレース１１００の記録時に共にsuperClassのインスタンスであったため、記録されたトレース１１００では、これら２つの仮想関数呼び出しに対しsuperClassのメンバmethodA()とmethodB()がそれぞれインラインされている。挿入部２１２Ｂはトレース１１００を読み込むと、２つの仮想関数呼び出しそれぞれに対し、virtualcall guard１１０２、１１０４として、superClassをレシーバ・オブジェクトobjの許可クラスとするクラス・テストと該クラス・テストの失敗をその実行の条件とするメソッド・テストとを挿入する。挿入されるメソッド・テストは、テストが成功した場合は実行を継続させ、失敗した場合は実行を終了させるテストである。挿入部２１２Ｂはまた、挿入したメソッド・テストそれぞれに対しプロファイラＢを挿入する。図１２に示すコード１２００はvirtualcall guard９０２及びプロファイラＢとして挿入するコードの一例であり、図１３に示すコード１３００は、virtualcall guard９０４及びプロファイラＢとして挿入するコードの一例である。
【００８１】
図１１（ｂ）、（ｃ）、（ｄ）は、上記説明した状況において１１（ａ）に示す記録されたトレース９００が実行された際の実行結果を示す。図１１（ｂ）に示す実行結果１１１０では、レシーバ・オブジェクトobjXの実行時のクラスはchildClass2であり、レシーバ・オブジェクトobjYの実行時のクラスはchildClass1である。いずれについてもトレース記録時のクラスsuperClassとは異なるため、いずれのメソッド・テストも実行されている。そして上述したようにchildClass2は、methodAをそのまま承継しているので、メソッド・テストは図１１（a）に示すvirtual call guard１１０２に対応する地点１１１２において成功している。同様に、クラスchildClass1も、methodBをそのまま承継しているので、メソッド・テストは図１１（a）に示すvirtual call guard１１０４に対応する地点１１１４において成功している。メソッド・テストが実行されることから地点１１１２と地点１１１４のそれぞれにおいてプロファイラ２２２Ｂが実行され、レシーバ・オブジェクトobjXの実行時のクラスとしてchildClass2が、objYの実行時のクラスとしてchildClass1がそれぞれテスト結果（成功）と共に記録される。
【００８２】
図１１（ｂ）に示す実行結果１１１０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjXの実行時のクラスchildClass2についてのメソッド・テストのテスト結果が成功であることから、上記挿入処理済のトレース１１００に含まれる対応するクラス・テストの許可クラスにクラスchildClass2を追加する。図１２に示すコード１２０２は、クラス・テストの許可クラスにプロファイルされた実行時のクラスchildClass2（参照番号１２０４）を追加することによって最適化されたvirtual call guard１１０２を示す。同様に、最適化部２１８Ｂは、レシーバ・オブジェクトobjYの実行時のクラスchildClass1についてのメソッド・テストのテスト結果が成功であることから、上記挿入処理済のトレース１１００に含まれる対応するクラス・テストの許可クラスにクラスchildClass1を追加する。図１３に示すコード１３０２は、クラス・テストの許可クラスにプロファイルされた実行時のクラスchildClass1（参照番号１３０４）を追加することによって最適化されたvirtual call guard１１０４を示す。
【００８３】
図１１（ｃ）に示す実行結果１１２０では、レシーバ・オブジェクトobjXとobjYの実行時のクラスは共にchildClass0でありトレース記録時のクラスsuperClassとは異なるため、いずれのメソッド・テストも実行されている。そして上述したようにchildClass0は、methodAとmethodBをそのまま承継しているので、メソッド・テストは図１１（ａ）に示すvirtualcall guard１１０２に対応する地点１１２２とvirtual callguard１１０４に対応する地点１１２４の両地点において成功している。メソッド・テストが実行されることから地点１１２２と地点１１２４のそれぞれにおいてプロファイラ２２２Ｂが実行され、レシーバ・オブジェクトobjXとobjYの実行時のクラスとしてchildClass0がテスト結果（成功）と共に記録される。
【００８４】
図１１（ｃ）に示す実行結果１１２０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjXの実行時のクラスchildClass0についてのメソッド・テストのテスト結果が成功であることから、上記挿入処理済のトレース１１００に含まれる対応するクラス・テストの許可クラスにクラスchildClass0を追加する。図１２に示すコード１２０６は、クラス・テストの許可クラスにプロファイルされた実行時のクラスchildClass0（参照番号１２０８）を追加することによって最適化されたvirtual call guard１１０２を示す。同様に、最適化部２１８Ｂは、レシーバ・オブジェクトobjYの実行時のクラスchildClass0についてのメソッド・テストのテスト結果が成功であることから、上記挿入処理済のトレース１１００に含まれる対応するクラス・テストの許可クラスにクラスchildClass0を追加する。図１３に示すコード１３０６は、クラス・テストの許可クラスにプロファイルされた実行時のクラスchildClass0（参照番号１３０８）を追加することによって最適化されたvirtual call guard１１０４を示す。
【００８５】
図１１（ｄ）に示す実行結果１１３０では、レシーバ・オブジェクトobjXとobjYの実行時のクラスは共にchildClass2でありトレース記録時のクラスsuperClassとは異なるため、いずれのメソッド・テストも実行されている。そして上述したようにchildClass2は、methodAについてはそのまま承継しているが、methodBについてはオーバーライドしている。そのため、メソッド・テストは図１１（ａ）に示すvirtual callguard１１０２に対応する地点１１３２では成功するが、virtual callguard１１０４に対応する地点１１３４では失敗している。メソッド・テストが実行されることから地点１１３２と地点１１３４のそれぞれにおいてプロファイラ２２２Ｂが実行され、レシーバ・オブジェクトobjXの実行時のクラスとしてchildClass2がテスト結果（成功）と共に、また、レシーバ・オブジェクトobjYの実行時のクラスとしてchildClass2がテスト結果（失敗）と共に記録される。
【００８６】
図１１（ｄ）に示す実行結果１１３０に対し、取得部２１４Ｂは上記プロファイル結果を取得して最適化部２１８Ｂへ渡す。最適化部２１８Ｂは、レシーバ・オブジェクトobjXの実行時のクラスchildClass2は、図１１（ｂ）の実行結果に対する最適化処理において許可クラスとして既に追加済みであるため何もしない。一方、最適化部２１８Ｂは、レシーバ・オブジェクトobjYの実行時のクラスchildClass2についてのメソッド・テスト結果が失敗であることから、上記挿入処理済のトレース１１００に含まれる対応するクラス・テストにクラスchildClass2を設定した拒絶クラスを新たに追加する。図１３に示すコード１３１０は、クラス・テストにプロファイルされた実行時のクラスchildClass2を拒絶クラスとして追加する（図１３の参照番号１３１２）ことによって最適化されたvirtual callguard１１０４を示す。
【００８７】
次に図１４を参照して、本発明の第２の実施形態に係る最適化装置２１０Ｂによる処理の流れを説明する。図１４に示す処理は、ステップ１４００より開始され、最適化装置２１０Ｂは、プロファイル結果を格納するための空のプロファイル・テーブル１４２４を作成する。作成するプロファイル・テーブル１４２４は、レシーバ・オブジェクトのフィールドと、実行時クラスのフィールドと、テスト結果のフィールドと、回数のフィールドとを有する。レシーバ・オブジェクトのフィールドのエントリには、
プロファイル対象のレシーバ・オブジェクトの名前が格納される。実行時クラスのフィールドのエントリには、プロファイル対象のレシーバ・オブジェクトの実行時のクラスが格納される。テスト結果のフィールドのエントリには、プロファイル対象のメソッド・テストのテスト結果が格納される。回数のフィールドのエントリには、該エントリと同一の内容がプロファイルされた回数が格納される。
【００８８】
続いて最適化装置２１０Ｂは、コード列格納部１４２０から次にコンパイル対象とするコード列２０６を読み出し、読み出したコード列２０６に含まれる各仮想関数に対しクラス・テストと該クラス・テストの失敗をその実行の条件とするメソッド・テスト、即ち型テストを挿入する（ステップ１４０２）。但し、上述したように、同一のレシーバ・オブジェクトを使用する仮想関数については、最適化装置２１０Ｂは挿入する型テストを１つにまとめる。最適化装置２１０Ａはまた挿入した型テストごと、メソッド・テストの実行を条件に、仮想関数の呼び出しに使用されたレシーバ・オブジェクトの実行時のクラスと、メソッド・テストのテスト結果と、プロファイルの回数とを記録するためのコードを挿入する（ステップ１４０２）。
【００８９】
挿入するコードは実行されると次のように動作する。即ち、直前に実行されたメソッド・テストのレシーバ・オブジェクトの名前と、現在のクラスと、メソッド・テストのテスト結果を取得する。続いて取得したレシーバ・オブジェクトの名前と現在のクラスとをキーとしてプロファイル・テーブル１４２４を検索する。マッチするエントリが存在する場合、そのエントリの回数フィールドの値を１増加する。マッチするエントリが存在しない場合、レシーバ・オブジェクトのフィールドを現在のレシーバ・オブジェクトの名前、実行時クラスのフィールドを現在のクラス、テスト結果のフィールドを現在のメソッド・テストのテスト結果、回数のフィールドを値１とするエントリを新たに追加する。挿入処理済のコード列２０６はその後コード列格納部１４２０に戻される。
【００９０】
続いて最適化装置２１０Ｂは、挿入処理済のコード列２０６が実行部２２０、又はコンパイラ２０８Ｂによりコンパイルされた場合にはＣＰＵ１により実行されたか否かを判定する（ステップ１４０４）。ステップ１４０４の判定処理は、実行されたとの判定がなされるまで繰り返し行われる。最適化装置２１０Ｂは、ステップ１４０４において実行されたと判定した場合（ステップ１４０４：ＹＥＳ）、プロファイル結果の取得を試みる（ステップ１４０６）。最適化装置２１０Ｂは、プロファイル結果を取得できたか否かを判定し（ステップ１４０８）、プロファイル結果を取得できなかった場合（ステップ１４０８：NO）、再びステップ１４０４の判定処理を行う。
【００９１】
一方、プロファイル結果を取得できた場合（ステップ１４０８：YES）、最適化装置２１０Ｂは、コード列２０６に含まれるレシーバ・オブジェクトごと、プロファイル・テーブル１４２４のテスト結果が「成功」である実行時クラスの中から、回数の多い上位ｍ個（ｍは１以上の整数）のエントリを選択する（ステップ１４１０）。同様に最適化装置２１０Ｂは、コード列２０６に含まれるレシーバ・オブジェクトごと、プロファイル・テーブル１４２４のテスト結果が「失敗」である実行時クラスの中から、回数の多い上位ｎ個（ｎは１以上の整数）のエントリを選択する（ステップ１４１０）。
【００９２】
続いて最適化装置２１０Ｂは、コード列格納部１４２０からステップ１４０２の挿入処理済のコード列２０６を読み出し、各クラス・テストについて、ステップ１４１０で対応するレシーバ・オブジェクトに対して「成功」クラスとして選択した上記ｍ個のエントリの実行時のクラスを用いて許可クラスを追加又は更新する（ステップ１４１２）。同様に、最適化装置２１０Ｂは、各クラス・テストについて、ステップ１４１０で対応するレシーバ・オブジェクトに対して「失敗」クラスとして選択した上記ｎ個のエントリの実行時のクラスを用いて拒絶クラスを追加又は更新する（ステップ１４１２）。許可クラス及び／又は拒絶クラスを追加又は更新されることによってvirtualcall guardを最適化されたコード列２０６はその後コード列格納部１４２０に戻される。そして処理は再びステップ１４０４に戻り、ステップ１４０４からステップ１４１２までの一連の処理がＳ１４１２において最適化されたコード列２０６に対し繰り返される。
【００９３】
次に図１５及び図１６を参照して、本発明による性能向上とコードサイズ削減の効果を検証する。図１５及び図１６に示すグラフは、トレース記録時のクラスのみを許可クラスとする従来技術のクラス・テストをvirtualcall guardとして用いた場合と、本発明の第１実施形態に係る最適化方法を適用して得られた複数のクラスを許可クラスとするクラス・テストをvirtualcall guardとして用いた場合の性能とコードサイズとを比較した実験結果である。図１５において、縦軸は従来技術の性能を基準としたパフォーマンスの改善率を示し、横軸はDaCapo benchmark suite（Dacapo-2006-10-MR2）ベンチマーク群の各プログラム名を示している。また、図１６において、縦軸は従来技術のJITコンパイル後のコードサイズに対する割合を示し、横軸は図１５と同じくDaCapo benchmark suiteの各プログラム名を示している。実験に使用したコンピュータは、4.0GHz動作のPOWER6を搭載し、オペレーティング・システムはAIX6.1であった。また実験結果は１６回の実行平均であり、許可クラスとして追加するクラスを上位４つに制限した。図１５に示すように、fopベンチマークを除く全てのベンチマークで性能向上が得られ、pmtベンチマークについては２５％もの性能向上が得られた。また、chartベンチマークを除く全てのベンチマークについてJITコンパイル後のコードサイズは減少した。
【００９４】
以上、実施形態を用いて本発明の説明をしたが、本発明の技術範囲は上記実施形態に記載の範囲には限定されない。例えば上記説明では、仮想関数の呼び出し先が実行時の単一のオブジェクトのクラスによって決定される（singledispatch）言語に本発明を適用した。しかし、本発明は複数の引数の型に応じて呼び出し先メソッドを実行時に選択できる（multidispatch）言語にも適用可能である。但しこの場合、２回目以降のvirtualcall guardを省略するためには、呼び出し先の決定に関係する全てのオブジェクトの組としてチェック済みであるという情報を伝播する必要がある。例えばオブジェクトＡとオブジェクトＢの組、及びオブジェクトＡとオブジェクトＣの組を型チェックしている場合であっても、オブジェクトＢとオブジェクトＣを用いて仮想関数呼び出しを行う場合にはその型チェックを省略できない。このように上記の実施形態に、種々の変更または改良を加えることが可能であることが当業者に明らかである。従って、そのような変更または改良を加えた形態も当然に本発明の技術的範囲に含まれる。
【図１】
2013235386.tif 000003
【図２】
2013235386.tif 000004
【図３】
2013235386.tif 000005
【図４】
2013235386.tif 000006
【図５】
2013235386.tif 000007
【図６】
2013235386.tif 000008
【図７】
2013235386.tif 000009
【図８】
2013235386.tif 000010
【図９】
2013235386.tif 000011
【図１０】
2013235386.tif 000012
【図１１】
2013235386.tif 000013
【図１２】
2013235386.tif 000014
【図１３】
2013235386.tif 000015
【図１４】
2013235386.tif 000016
【図１５】
2013235386.tif 000017
【図１６】
2013235386.tif 000018