Je „call site“ nějaký automatický kód generovaný překladačem – s tímto pojmem se často setkávám a zní to, jako by metoda volání byla jednoduše označována jako „call site“ – což doslova zní dobře, ale věřím, že má nějaké hlubší spletitosti. A pokud je „call site“ kód generovaný kompilátorem – za jakých okolností je to vyžadováno?
Ačkoli mluvím v kontextu C # .Net, vypadá to jako standardní terminologie. Ocenil bych jakékoli jasné / přesné vysvětlení na několika příkladech.
Komentáře
- Ve zdrojovém kódu i v automatickém režimu existuje pojem volání. -generovaný objektový kód.
- Možná byste se měli podívat na to, jak jsou generovány weby volání pro dynamickou operaci v C # 4 a vyšší. Jsou docela zajímavé.
- @EricLippert Díky. Naštěstí jsem našel odkaz , kde jste to popsali docela krásně. Nemohl jsem však najít žádný váš blog, který by konkrétně popisoval generování webových stránek pro volání.
Odpověď
„Volejte web ”Odkazuje na místo, kde se volá funkce nebo metoda. Je to běžný termín v konstrukci kompilátoru a není specifický pro C #.
foo(); // call site void foo() { ... } // function definition
Web volání není žádný speciální generovaný kód. Ale na místě volání kompilátor vydá pokyny k volání funkce. Typicky tyto:
- Uloží aktuální kontext do rámce zásobníku.
- Uloží všechny argumenty podle konvence volání cílové funkce.
- Zavolejte cílovou funkci, která může vyžadovat odeslání metody.
- Načíst návratovou hodnotu podle konvence volání.
- Obnovte kontext z rámce zásobníku.
Odeslání metody může vyžadovat spuštění komplikovaného kódu, aby bylo možné najít funkci, která by se měla skutečně volat. To je nutné při volání metod virtual
, zejména metod přes rozhraní. Kompletní postup odeslání metody může být poměrně nákladný (často O (n) v počtu implementovaných rozhraní nebo O (n) v počtu dostupných metod). Většinu času (obvykle 70–90%) však web volajícího uvidí objekty stejného typu. Pak má smysl uložit výsledek vyhledávání metody do mezipaměti. Kompilátor pak může vygenerovat takový kód na stránce volání:
static lastType = null; static lastMethod = null; if (type(instance) != lastType) { lastType = type(instance); lastMethod = performMethodLookup(instance, methodName); } result = lastMethod(instance, args);
Toto se nazývá monomorfní vložená mezipaměť . Rozhraní .NET CLR vyvinulo trochu komplikovanější přístup s názvem Virtual Stub Dispatch . Místo provádění odeslání na místě volání kompiluje běhové JIT metody stubu. Existují různé pahýly pro provedení procedury odeslání celé metody a pro použití metody v mezipaměti. Na místě volání pak máme pouze volání stubu a stub přesměruje hovor na skutečný cíl. V závislosti na statistikách tohoto místa volání bude strojový kód na místě volání opraven tak, aby používal jiný útržek.
Odpovědět
Nejběžnějším použitím call-site je pravděpodobně to jak je v současné době deklarováno na Wikipedii : není to nic jiného než místo v nějakém kódu, kde volání na je provedena funkce nebo podprogram. Je to zcela obecný pojem, který lze použít na všechny druhy jazyků (a rozhodně nemá nic společného s dynamickým programováním!).
Obvykle používám tento výraz (na rozdíl od pouze „call“), aby bylo jasné, že se diskutuje o syntaxi a sémantice kódu, kde se volá funkce / metoda / podprogram, na rozdíl od základní sémantiky volání, nebo sémantiky v definici funkce / metody: v tímto způsobem to absolutně není o kompilátoru nebo jakémkoli generovacím kódu (i když tento termín bude i nadále platit pro kód generovaný kompilátorem / běhovým modulem, jak si myslím už amon probral), je o přenesení konkrétního kódu, který se převádí na volání, do kontextu a někdy i kódu v bezprostřední blízkosti.
Toto je druh obrázku, který mám v hlavě:
call-site call call-target/method definition --> --> int.TryParse(str, out i); (runtime) public static bool TryPars(...
„ Call-site “je užitečný termín pro mluvení o syntaxi uskutečnění hovoru a sémantice, která ovlivňuje volajícího (podrobně amon). Zvažte například nový in
modifikátor v C #, „volání“, které předá argument jako „in“, má s ním spojenou určitou sémantiku (předává se ref, případně po kopie), ale to nemusí být nutně zřejmé ze syntaxe „na stránce volání“, kde in
není povinný. Myšlenka spočívá v tom, že sémantika call-site (tj. Chování, které ovlivňuje volajícího / call-site) předávání argumentu odkazem pomocí in
jsou blízké dost na předávání hodnoty, kterou není třeba rozlišovat pomocí syntaxe na call-site .Nesouhlasím s tímto tvrzením a těžko bych o tom diskutoval bez výrazu jako „call-site“!
Další příklad: dynamické volání (např. Pro metodu virtuální / rozhraní) má něco komplikované chování za běhu (opět podrobně amon) a není známo, při kompilaci, která metoda bude volána, ale vše, na čem „call-site“ záleží, je sémantika dispečinku tohoto volání: pokud voláte ToString()
na object
vám nezajímá opravdu , že se skutečně jedná o string
na call-site; záleží vám jen na tom, aby object
vystavil virtuální ToString()
metodu (je to až po dobu běhu zjistit, kterou metodu skutečně zavolat). Ve skutečnosti na call-site (např. V C #) není ze syntaxe nutně jasné, zda se jedná o virtuální volání: rozdíl mezi virtuálním a nevirtuálním voláním je často považován za dostatečně nedůležitý at the call- web , který pro programátora nemusí být jednoznačně na call-site (i když je pro kompilátor / běh životně důležité uskutečnit smysluplné volání)
Jeden poslední příklad: zvažte C # „s ref
a C ++“ s &
: sémantiku na call-site v obou jazyky jsou v obou jazycích téměř stejné: předává se odkaz, nikoli hodnota, ale každý jazyk má jinou syntaxi na call-site, kde C # vyžaduje ref
a C ++ ne vyžadují &
(nebo něco podobného). Znovu jazykoví designéři udělali několik rozhodnutí o syntaxi o tom, jak jsou volání reprezentována na call-site, informovaná sémantikou na call-site. (Dávám přednost syntaxi call-site C #, protože odhaluje sémantiku call-site, což podle mého názoru jako programátora musím potvrdit, když jsem takový hovor uskutečnil). Je snad zřejmé, že definice metody musí vědět, že přijímá parametr odkazem, protože mění chování jeho úpravy (např. Pomocí =
). Mohli byste však namítnout, že runtime nezajímá (v takových staticky zadaných jazycích, kde je runtime-dispečink nominálně informován): tuto hodnotu musí jednoduše dostat od volajícího na volaného „Nezajímá mě, zda se jedná o referenci, či nikoli, to je starost o call-site a call-target.
Volněji,„ call-site “může odkazovat na kód, který označuje volání, a také „přidružený“ kód kolem něj (na rozdíl od „volání“). Například v C # by se dalo odkazovat na definování fiktivní proměnné „at“ na call-site, např. při volání metody TryParse
:
int dummy; bool looksLikeAnInt = int.TryParse(str, out dummy);
Celý tento „blok“ lze považovat za součást stránky volání. Považuji to za méně „přesný“ význam, ale to mě nepřestává používat.