「呼び出しサイト」はコンパイラによって生成された自動コードです-この用語に頻繁に出くわし、メソッドの呼び出しは単に「呼び出しサイト」と呼ばれているようです-文字通り問題ないように聞こえますが、さらに複雑な部分があると思います。また、「呼び出しサイト」がコンパイラで生成されたコードである場合、どのような状況でこれが必要ですか?
C#.Netのコンテキストで話していますが、これは標準的な用語のようです。いくつかの例を使用して、明確で正確な説明をいただければ幸いです。
コメント
- ソースコードと自動の両方に呼び出しサイトの概念があります。 -生成されたオブジェクトコード。
- C#4以降の動的操作でコールサイトがどのように生成されるかを調べたい場合があります。彼らは非常に興味深いです。
- @EricLippertありがとう。幸い、リンクがとても美しく説明されているのを見つけました。ただし、コールサイトの生成について具体的に詳しく説明しているブログは見つかりませんでした。
回答
「コールサイト」とは、関数またはメソッドが呼び出される場所を指します。これはコンパイラ構築の一般的な用語であり、C#に固有のものではありません。
foo(); // call site void foo() { ... } // function definition
呼び出しサイトは、特別に生成されたコードではありません。しかし、呼び出しサイトでは、コンパイラーは関数を呼び出すための命令を出します。通常、これらは次のとおりです。
- 現在のコンテキストをスタックフレームに保存します。
- ターゲット関数の呼び出し規約に従ってすべての引数を保存します。
- ターゲット関数を呼び出します。メソッドのディスパッチが必要になる場合があります。
- 呼び出し規約に従って戻り値を取得します。
- スタックフレームからコンテキストを復元します。
メソッドディスパッチでは、実際に呼び出す必要のある関数を見つけるために、複雑なコードを実行する必要がある場合があります。これは、virtual
メソッド、特にインターフェイスを介してメソッドを呼び出すときに必要です。完全なメソッドディスパッチ手順は、かなりコストがかかる場合があります(多くの場合、実装されたインターフェイスの数でO(n)、または使用可能なメソッドの数でO(n))。ただし、ほとんどの場合(通常、70〜90%)、コールサイトには同じタイプのオブジェクトが表示されます。次に、メソッドルックアップの結果をキャッシュすることは理にかなっています。コンパイラは、呼び出しサイトで次のようなコードを生成する可能性があります。
static lastType = null; static lastMethod = null; if (type(instance) != lastType) { lastType = type(instance); lastMethod = performMethodLookup(instance, methodName); } result = lastMethod(instance, args);
これは単形として知られています。インラインキャッシュ。 .NET CLRは、仮想スタブディスパッチと呼ばれるもう少し複雑なアプローチを開発しました。呼び出しサイトでディスパッチを実行する代わりに、ランタイムJITはスタブメソッドをコンパイルします。完全なメソッドディスパッチ手順を実行するため、およびキャッシュされたメソッドを使用するためのさまざまなスタブがあります。コールサイトでは、スタブへの呼び出しのみが行われ、スタブはその呼び出しを実際のターゲットに転送します。このコールサイトの統計に応じて、コールサイトのマシンコードにパッチが適用され、別のスタブが使用されます。
回答
call-siteの最も一般的な使用法は、おそらく現在ウィキペディアで宣言されているです。これは、コード内で呼び出しが行われる場所にすぎません。関数またはサブルーチンが作成されます。これは、あらゆる種類の言語に適用できる完全に一般的な用語です(そして、確かに動的プログラミングとは関係ありません!)。
私は通常、使用される用語を聞きます(用語「呼び出し」)呼び出しの基礎となるセマンティクス、または関数/メソッド定義のセマンティクスとは対照的に、関数/メソッド/サブルーチンが呼び出されるコードの構文とセマンティクスについて説明していることを明確にします。このように、コンパイラや生成コードについては絶対に ありません(amonがすでに説明したように、この用語はコンパイラ/ランタイムによって生成されたコードにも適用されますが)、呼び出しに変換される特定のコードをコンテキストに取り込むことについて、場合によってはすぐ近くにあるコードについて。
これは私の頭の中にあるようなものです:
call-site call call-target/method definition --> --> int.TryParse(str, out i); (runtime) public static bool TryPars(...
「call-site」は、呼び出しを行う構文、および呼び出し元に影響を与えるセマンティクス(amonで詳しく説明)について説明するのに役立つ用語です。たとえば、C#の新しいin
修飾子について考えてみます。引数を「in」として渡す「呼び出し」には、特定のセマンティクスが関連付けられています(refによって渡されます。コピー)が、これは「呼び出しサイトで」の構文から必ずしも明確ではありません。ここで、in
は必須ではありません。アイデアは、in
を参照して引数を渡す呼び出しサイトのセマンティクス(つまり、呼び出し元/呼び出しサイトに影響を与える動作)が近いということです。値を渡す場合は、呼び出しサイトで構文によって明確にする必要がないほど十分です。 私はこの主張に同意しません。「call-site」のような用語がないと議論するのに苦労します!
別の例:動的呼び出し(仮想/インターフェイスメソッドなど)には多少の問題があります複雑なランタイム動作(これもamonで詳しく説明されています)であり、コンパイル時にどのメソッドが呼び出されるかはわかりませんが、「呼び出しサイト」が気にするのは、その呼び出しをディスパッチするセマンティクスだけです。ividを呼び出している場合object
の= “0978a39a2b”>
では、実際にstring
本当に気にしません。
呼び出しサイトで; object
が仮想ToString()
メソッドを公開することだけを気にします(実行時までです)実際に呼び出すメソッドを決定するため)。実際、呼び出しサイト(C#など)では、これが仮想呼び出しであるかどうかが構文から必ずしも明確ではありません。仮想呼び出しと非仮想呼び出しの区別は、呼び出し時に十分に重要でないと見なされることがよくあります。サイトは、プログラマーが呼び出しサイトで明確にする必要がないことを示しています(コンパイラー/ランタイムが意味のある呼び出しを行うことは非常に重要ですが)
最後の例:C#のref
とC ++の&
を検討してください:両方の呼び出しサイトでのセマンティクス言語は両方の言語でほぼ同じです。値ではなく参照が渡されますが、呼び出しサイトでは言語ごとに構文が異なります。C#ではref
が必要であり、C ++では必要ありません。 &
(またはそのようなもの)が必要です。繰り返しになりますが、言語設計者は、呼び出しサイトでのセマンティクスによって通知された、呼び出しサイトでの呼び出しの表現方法について構文上の決定を行いました。 (私はC#の呼び出しサイト構文を好みます。これは、呼び出しサイトのセマンティクスを公開するためです。プログラマーとして、このような呼び出しを行ったときに確認する必要があると思います)。メソッド定義は、パラメータを変更する動作を変更するため(=
など)、参照によってパラメータを受け取っていることを知る必要があることは明らかです。ただし、ランタイムは 気にしないと主張することもできます(静的に型指定された言語では、ランタイムディスパッチが名目上通知されます)。呼び出し元から呼び出し先にこの値を取得する必要があります。 、それが参照であるかどうかは関係ありません。これは、コールサイトとコールターゲットの懸念事項です。
もっと大まかに言うと、「コールサイト」は参照する場合があります。呼び出しを示すコードとその周囲の「関連付けられた」コード(「呼び出し」だけではなく)。たとえば、C#では、呼び出しサイトの「at」でダミー変数を定義することを参照できます。 TryParse
メソッドを呼び出す場合:
int dummy; bool looksLikeAnInt = int.TryParse(str, out dummy);
この「ブロック」全体は、コールサイトの一部と見なすことができます。これは「正確」ではない意味だと思いますが、それでも使用を止めることはできません。