¿El ' sitio de llamada ' genera un código automático generado por el compilador?

¿Es «llamar al sitio» un código automático generado por el compilador? Me encuentro con este término con frecuencia y parece que el método de llamada se denomina simplemente «llamar al sitio». – que literalmente suena bien, pero creo que tiene algunas complejidades más profundas. Y si «llamar al sitio» es un código generado por el compilador, ¿en qué circunstancias es necesario?

Aunque estoy hablando en el contexto de C # .Net, parece que se trata de una terminología estándar. Agradecería una explicación clara / precisa con algunos ejemplos.

Comentarios

  • Existe una noción de sitio de llamada tanto en el código fuente como en el -código de objeto generado.
  • Es posible que desee ver cómo se generan los sitios de llamadas para una operación dinámica en C # 4 y superior. Son bastante interesantes.
  • @EricLippert Gracias. Afortunadamente, encontré un enlace donde lo describiste muy bien. Sin embargo, no pude encontrar ningún blog suyo que detallara específicamente la generación del sitio de llamadas.

Responder

“Llamar al sitio ”Se refiere al lugar donde se llama a una función o método. Es un término común en la construcción de compiladores y no es específico de C #.

foo(); // call site void foo() { ... } // function definition 

El sitio de llamada no es un código generado especial. Pero en el sitio de la llamada, el compilador emite instrucciones para llamar a la función. Por lo general, estos:

  • Guardar el contexto actual en un marco de pila.
  • Almacenar todos los argumentos de acuerdo con la convención de llamada de la función de destino.
  • Llame a la función de destino, que puede requerir el envío del método.
  • Recupere el valor de retorno de acuerdo con la convención de llamada.
  • Restaura el contexto del marco de pila.

El envío de métodos puede requerir la ejecución de un código complicado para encontrar la función que realmente debería llamarse. Esto es necesario al llamar a métodos virtual, especialmente métodos a través de una interfaz. El procedimiento completo de envío de métodos puede ser bastante costoso (a menudo O (n) en el número de interfaces implementadas u O (n) en el número de métodos disponibles). Pero la mayoría de las veces (típicamente del 70 al 90%), un sitio de llamada verá objetos del mismo tipo. Entonces tiene sentido almacenar en caché el resultado de la búsqueda del método. El compilador podría generar un código como este en el sitio de la llamada:

static lastType = null; static lastMethod = null; if (type(instance) != lastType) { lastType = type(instance); lastMethod = performMethodLookup(instance, methodName); } result = lastMethod(instance, args); 

Esto se conoce como un monomórfico caché en línea . .NET CLR desarrolló un enfoque un poco más complicado llamado Virtual Stub Dispatch . En lugar de realizar el envío en el sitio de la llamada, el tiempo de ejecución JIT compila los métodos de código auxiliar. Hay diferentes códigos auxiliares para realizar el procedimiento completo de envío de métodos y para utilizar un método almacenado en caché. En el sitio de la llamada, solo tenemos una llamada al stub, y el stub reenviará la llamada al objetivo real. Dependiendo de las estadísticas para este sitio de llamada, el código de máquina en el sitio de llamada será parcheado para usar un código auxiliar diferente.

Responder

El uso más típico de call-site es probablemente que como se declara actualmente en Wikipedia : no es más que el lugar en algún código donde una llamada a un se realiza la función o subrutina. Es un término completamente general que se puede aplicar a todo tipo de lenguajes (¡y ciertamente no tiene nada que ver con la programación dinámica!).


Por lo general escucho el término usado (en oposición a solo el término «llamada») para dejar en claro que se está discutiendo la sintaxis y la semántica del código donde se llama a una función / método / subrutina, en oposición a la semántica subyacente de la llamada, o la semántica en la definición de función / método: en de esta manera, es absolutamente no sobre el compilador o cualquier código de generación (aunque el término todavía se aplicará al código generado por el compilador / tiempo de ejecución, como creo que amon ya ha discutido), es acerca de traer el código específico que se traduce en una llamada en contexto y, a veces, el código en las inmediaciones.

Este es el tipo de imagen que tengo en mi cabeza:

 call-site call call-target/method definition --> --> int.TryParse(str, out i); (runtime) public static bool TryPars(... 

El» call-site «es un término útil para hablar sobre la sintaxis de realizar una llamada y la semántica que afecta a la persona que llama (detallada por amon). Considere, por ejemplo, el nuevo in modificador en C #, una «llamada» que pasa un argumento como «in» tiene cierta semántica asociada (se pasa por ref, posiblemente después una copia), pero esto no está necesariamente claro en la sintaxis «en el sitio de la llamada», donde in no es obligatorio. La idea es que la semántica del call-site (es decir, el comportamiento que influye en la persona que llama / call-site) de pasar un argumento por referencia con in está cerca lo suficiente para los de pasar por valor que no es necesario eliminar la ambigüedad por la sintaxis en el sitio de llamada .No estoy de acuerdo con esta afirmación y «me costaría mucho discutirlo sin un término como» sitio de llamada «.

Otro ejemplo: una llamada dinámica (por ejemplo, para un método de interfaz virtual) tiene algo comportamientos complicados en tiempo de ejecución (nuevamente, detallados por amon) y no se sabe en el momento de la compilación qué método se llamará, pero todo lo que le importa al «call-site» es la semántica del envío de esa llamada: si está llamando a ToString() en un object, no realmente le importa que en realidad sea un string en el sitio de llamada; solo te importa que object exponga un método ToString() virtual (depende del tiempo de ejecución para averiguar qué método llamar realmente). De hecho, en el sitio de la llamada (por ejemplo, en C #) no está necesariamente claro en la sintaxis si se trata de una llamada virtual: la distinción entre una llamada virtual y no virtual a menudo se considera lo suficientemente poco importante en la llamada- sitio que no necesita ser desambigua para el programador en el sitio de llamada (aunque es de vital importancia para el compilador / tiempo de ejecución hacer una llamada significativa)

Un último ejemplo: considere C # «s ref y C ++» s &: la semántica en el sitio de llamada en ambos Los idiomas son casi iguales en ambos idiomas: se pasa una referencia en lugar de un valor, pero cada idioma tiene una sintaxis diferente en el sitio de llamada, donde C # requiere ref y C ++ no require & (o algo así). Una vez más, los diseñadores del lenguaje han tomado algunas decisiones de sintaxis sobre cómo se representan las llamadas en el sitio de llamadas, informadas por la semántica en el sitio de llamadas. (Prefiero la sintaxis del sitio de llamadas de C # porque expone la semántica del sitio de llamadas, que creo que yo, como programador, debería tener que reconocer cuando hice tal llamada). Es de esperar que sea obvio que la definición del método necesita saber que está recibiendo un parámetro por referencia, porque cambia el comportamiento de modificarlo (por ejemplo, con =). Sin embargo, se podría argumentar que al tiempo de ejecución no le importa (en esos lenguajes tipados estáticamente, donde el envío del tiempo de ejecución está nominalmente informado): solo tiene que obtener este valor del llamador al destinatario de la llamada , no le importa si es una referencia o no, eso es una preocupación para el sitio de llamada y el destino de la llamada.


De manera más vaga, «sitio de llamada» podría referirse a el código que indica una llamada, así como el código «asociado» a su alrededor (a diferencia de solo la «llamada»). En C #, por ejemplo, uno podría referirse a definir una variable ficticia «en» un sitio de llamada, p. al llamar a un método TryParse :

int dummy; bool looksLikeAnInt = int.TryParse(str, out dummy); 

Todo este «bloque» podría considerarse parte del sitio de llamada. Consideraría que este es un significado menos «preciso», pero eso no me impide usarlo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *