Est-ce que « call site » est un code automatique généré par le compilateur – je rencontre souvent ce terme et il semble que la méthode dappel est simplement appelée « site dappel » – ce qui sonne littéralement bien, mais je pense quil a des subtilités plus profondes. Et si « call site » est du code généré par le compilateur – dans quelles circonstances cela est-il nécessaire?
Bien que je parle dans le contexte de C # .Net, mais cela semble être une terminologie standard. Japprécierais toute explication claire / précise avec quelques exemples.
Commentaires
- Il y a une notion de site dappel à la fois dans le code source et dans lauto – code objet généré.
- Vous voudrez peut-être examiner comment les sites dappel sont générés pour une opération dynamique en C # 4 et au-dessus. Ils sont assez intéressants.
- @EricLippert Merci. Heureusement, jai trouvé lien où vous lavez décrit assez bien. Cependant, je nai trouvé aucun blog de votre part détaillant spécifiquement la génération du site dappel.
Réponse
« Appel site »Fait référence à lendroit où une fonction ou une méthode est appelée. Cest un terme courant dans la construction du compilateur, et non spécifique à C #.
foo(); // call site void foo() { ... } // function definition
Le site dappel nest pas un code généré spécial. Mais sur le site dappel, le compilateur émet des instructions pour appeler la fonction. En règle générale, ceux-ci:
- Enregistrer le contexte actuel dans un cadre de pile.
- Stocker tous les arguments selon la convention dappel de la fonction cible.
- Appelez la fonction cible, ce qui peut nécessiter lenvoi de méthode.
- Récupérez la valeur de retour selon la convention dappel.
- Restaurez le contexte à partir du cadre de pile.
La répartition de la méthode peut nécessiter un code compliqué à exécuter afin de trouver la fonction qui devrait réellement être appelée. Ceci est nécessaire lors de lappel des méthodes virtual
, en particulier des méthodes via une interface. La procédure denvoi de méthode complète peut être assez coûteuse (souvent O (n) dans le nombre dinterfaces implémentées, ou O (n) dans le nombre de méthodes disponibles). Mais la plupart du temps (généralement 70 à 90%), un site dappel verra des objets du même type. Il est alors judicieux de mettre en cache le résultat de la recherche de méthode. Le compilateur peut alors générer un code comme celui-ci sur le site dappel:
static lastType = null; static lastMethod = null; if (type(instance) != lastType) { lastType = type(instance); lastMethod = performMethodLookup(instance, methodName); } result = lastMethod(instance, args);
Ceci est connu sous le nom de monomorphe cache en ligne . Le .NET CLR a développé une approche légèrement plus compliquée appelée Virtual Stub Dispatch . Au lieu de faire la répartition sur le site dappel, les méthodes de stub de compilation JIT du runtime. Il existe différents stubs pour effectuer la procédure de répartition complète de la méthode et pour utiliser une méthode mise en cache. Sur le site dappel, nous navons alors quun appel au stub, et le stub transférera lappel vers la cible réelle. En fonction des statistiques de ce site dappel, le code machine du site dappel sera corrigé pour utiliser un stub différent.
Réponse
Lutilisation la plus courante de call-site est probablement celle telle quelle est actuellement déclarée sur Wikipédia : ce nest rien de plus que lendroit dans un code où un appel à un fonction ou sous-programme est créé. Cest un terme tout à fait général qui peut être appliqué à toutes sortes de langages (et certainement rien à voir avec la programmation dynamique!).
Jentends habituellement le terme utilisé (par opposition à juste le terme « appel ») pour indiquer clairement que lon discute de la syntaxe et de la sémantique du code où une fonction / méthode / sous-routine est appelée, par opposition à la sémantique sous-jacente de lappel, ou la sémantique à la définition de fonction / méthode: in de cette façon, il ne sagit absolument pas du compilateur ou de tout code de génération (même si le terme sappliquera toujours au code généré par le compilateur / runtime, comme je pense que amon la déjà discuté), cest de mettre en contexte le code spécifique qui se traduit par un appel, et parfois le code dans le voisinage immédiat.
Voici le genre dimage que jai en tête:
call-site call call-target/method definition --> --> int.TryParse(str, out i); (runtime) public static bool TryPars(...
Le » site dappel « est un terme utile pour parler de la syntaxe dun appel, et de la sémantique qui affecte lappelant (détaillée par amon). Considérons, par exemple, le nouveau modificateur in
en C #, un « call » qui passe un argument comme « in » a une certaine sémantique qui lui est associée (il est passé par ref, éventuellement après une copie), mais ce nest pas nécessairement clair de la syntaxe « au site dappel », où in
nest « pas obligatoire. Lidée est que la sémantique du site dappel (cest-à-dire le comportement qui influence lappelant / le site dappel) de passer un argument par référence avec in
sont proches assez à ceux du passage par valeur quil na pas besoin de lever lambiguïté par la syntaxe sur le site dappel .Je ne suis pas daccord avec cette affirmation, et jaurais du mal à en discuter sans un terme comme « call-site »!
Un autre exemple: un appel dynamique (par exemple pour une méthode virtuelle / interface) comportements dexécution compliqués (encore une fois, détaillés par amon) et on ne sait pas au moment de la compilation quelle méthode sera appelée, mais tout le « site dappel » se soucie de la sémantique de la distribution de cet appel: si vous appelez ToString()
sur un object
, vous ne vous souciez pas vraiment quil sagit en fait dun string
sur le site de lappel; vous vous souciez seulement que object
expose une méthode virtuelle ToString()
(cest à la hauteur de lexécution pour déterminer la méthode à appeler). En effet, sur le site de lappel (par exemple en C #), il nest pas forcément clair daprès la syntaxe sil sagit dun appel virtuel: la distinction entre un appel virtuel et non virtuel est souvent considérée comme assez insignifiante lors de lappel. site quil na pas besoin dêtre levé pour le programmeur sur le site dappel (même sil est dune importance vitale pour le compilateur / runtime de faire un appel significatif)
Un dernier exemple: considérons C # « s ref
et C ++ » s &
: la sémantique au site dappel dans les deux langue sont à peu près les mêmes dans les deux langues: une référence est passée plutôt quune valeur, mais chaque langue a une syntaxe différente sur le site dappel, où C # nécessite ref
et C ++ ne le fait pas nécessitent &
(ou quelque chose comme ça). Encore une fois, les concepteurs de langage ont pris des décisions de syntaxe sur la façon dont les appels sont représentés sur le site dappel, informés par la sémantique sur le site dappel. (Je préfère la syntaxe du site dappel C # car elle expose la sémantique du site dappel, ce que je crois que je devrais devoir reconnaître en tant que programmeur lorsque jai effectué un tel appel). Il est, espérons-le, évident que la définition de méthode doit savoir quelle reçoit un paramètre par référence, car cela change le comportement de sa modification (par exemple avec =
). Vous pourriez cependant affirmer que le runtime ne se soucie pas (dans ces langages statiquement typés, où le runtime-dispatch est nominalement informé): il doit juste obtenir cette valeur de lappelant à lappelé , peu importe quil sagisse dune référence ou non, cest une préoccupation pour le site dappel et la cible dappel.
Plus vaguement, « call-site » pourrait faire référence à le code qui indique un appel ainsi que le code « associé » qui lentoure (par opposition au seul « appel »). En C #, par exemple, on pourrait se référer à la définition dune variable factice « à » un site dappel, par exemple lors de lappel dune méthode TryParse
:
int dummy; bool looksLikeAnInt = int.TryParse(str, out dummy);
Tout ce « bloc » pourrait être considéré comme faisant partie du site dappel. Je considère que cest une signification moins « précise », mais cela ne mempêche pas de lutiliser.