Il codice del compilatore 'call site' ha generato il codice auto?

0

Il "sito di chiamata" è un codice auto generato dal compilatore - mi imbatto spesso in questo termine e sembra che il metodo di chiamata venga semplicemente chiamato "sito di chiamata", che suona letteralmente bene ma credo che abbia alcune complessità più profonde. E se "call site" è codice generato dal compilatore - in quali circostanze è richiesto?

Anche se sto parlando nel contesto di C # .Net, ma questa sembra essere la terminologia standard. Gradirei qualsiasi spiegazione chiara / precisa con alcuni esempi.

    
posta Rahul Agarwal 11.02.2018 - 08:18
fonte

2 risposte

5

"Call site" si riferisce al luogo in cui viene chiamata una funzione o un metodo. È un termine comune nella costruzione del compilatore e non specifico per C #.

foo();  // call site

void foo() { ... } // function definition

Il sito di chiamata non è un codice generato speciale. Ma nel sito di chiamata, il compilatore emette le istruzioni per chiamare la funzione. In genere, questi:

  • Salva il contesto corrente in uno stack frame.
  • Archivia tutti gli argomenti in base alla convenzione di chiamata della funzione di destinazione.
  • Chiama la funzione obiettivo, che potrebbe richiedere l'invio del metodo.
  • Recupera il valore restituito in base alla convenzione di chiamata.
  • Ripristina il contesto dal frame dello stack.

La spedizione del metodo potrebbe richiedere l'esecuzione di un codice complicato per trovare la funzione che dovrebbe essere effettivamente chiamata. Questo è necessario quando si chiamano i metodi virtual , in particolare i metodi attraverso un'interfaccia. La procedura di invio del metodo completo può essere piuttosto costosa (spesso O (n) nel numero di interfacce implementate o O (n) nel numero di metodi disponibili). Ma la maggior parte delle volte (in genere il 70-90%), un sito di chiamata vedrà oggetti dello stesso tipo. Quindi ha senso memorizzare nella cache il risultato della ricerca del metodo. Il compilatore potrebbe quindi generare un codice come questo nel sito di chiamata:

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

Si tratta di una cache in linea monomorfica . .NET CLR ha sviluppato un approccio un po 'più complicato chiamato Virtual Stub Dispatch . Invece di eseguire la spedizione nel sito di chiamata, il runtime JIT compila i metodi di stub. Esistono diversi stub per eseguire la procedura di invio del metodo completo e per l'utilizzo di un metodo memorizzato nella cache. Nel sito di chiamata, quindi, abbiamo solo una chiamata allo stub e lo stub inoltrerà la chiamata al target effettivo. A seconda delle statistiche di questo sito di chiamata, il codice macchina nel sito di chiamata verrà corretto per utilizzare uno stub diverso.

    
risposta data 11.02.2018 - 11:06
fonte
1

L'uso più tipico del call-site è probabilmente come attualmente dichiarato su Wikipedia : non è altro che il inserire in qualche codice dove viene effettuata una chiamata a una funzione o subroutine. È un termine completamente generale che può essere applicato a tutti i tipi di linguaggi (e sicuramente non ha nulla a che fare con la programmazione dinamica!).

Solitamente ascolto il termine usato (in opposizione al solo termine "call") per chiarire che si sta discutendo la sintassi e la semantica del codice in cui viene chiamata una funzione / metodo / subroutine, in opposizione al sottostante semantica della chiamata, o semantica alla definizione di funzione / metodo: in questo modo, è assolutamente non sul compilatore o qualsiasi codice di generazione (anche se il termine si applicherà ancora al codice generato dal compiler / runtime, come penso abbia già discusso di amon), si tratta di portare il codice specifico che si traduce in una chiamata nel contesto, e talvolta il codice nelle immediate vicinanze.

Questo è il tipo di immagine che ho in testa:

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

Il "call-site" è un termine utile per parlare della sintassi di effettuare una chiamata e della semantica che influenza il chiamante (dettagliato da amon). Si consideri, ad esempio, il nuovo modificatore in in C #, una 'chiamata' che passa un argomento come 'in' ha una certa semantica ad essa associata (è passata da ref, probabilmente dopo una copia), ma questo non è necessariamente chiaro dalla sintassi 'sul sito di chiamata', dove in non è obbligatorio. L'idea è che la semantica del sito di chiamata (cioè il comportamento che influenza il chiamante / il sito di chiamata) di passare un argomento per riferimento con in siano abbastanza vicine a quelle di passaggio per valore che non ha bisogno di essere disambiguato dalla sintassi sul sito di chiamata . Non sono d'accordo con questa affermazione, e avrei difficoltà a discuterne senza un termine come "call-site"!

Un altro esempio: una chiamata dinamica (ad esempio per un metodo di interfaccia virtuale) ha comportamenti di runtime un po 'complicati (di nuovo, dettagliati da amon) e non è noto al momento della compilazione quale metodo verrà chiamato, ma tutta la chiamata -site 'si preoccupa della semantica di dispacciamento di quella chiamata: se stai chiamando ToString() su object , non ti preoccupi veramente che in realtà è un string alla chiamata -posto; a te interessa solo che object esponga un metodo virtuale ToString() (spetta al runtime calcolare il metodo per chiamare effettivamente). In effetti, nel sito di chiamata (ad esempio in C #) non è necessariamente chiaro dalla sintassi se si tratti di una chiamata virtuale: la distinzione tra una chiamata virtuale e una non virtuale è spesso considerata abbastanza importante alla chiamata sito che non ha bisogno di essere disambiguato per il programmatore sul sito di chiamata (anche se è di vitale importanza che il compilatore / runtime effettui una chiamata significativa)

Un ultimo esempio: considera il ref di C # e il & di C ++: la semantica del sito di chiamata in entrambe le lingue è praticamente la stessa in entrambe le lingue: viene passato un riferimento anziché un valore, ma ogni lingua ha sintassi diversa sul sito di chiamata, dove C # richiede ref e C ++ non richiede & (o qualcosa del genere). Ancora una volta, i progettisti di linguaggi hanno preso alcune decisioni sulla sintassi su come le chiamate sono rappresentate nel sito di chiamata, informate dalla semantica sul sito di chiamata. (Preferisco la sintassi del sito di call di C # perché espone la semantica del sito di chiamata, che credo che come programmatore dovrei riconoscere quando ho fatto una tale chiamata). È auspicabile che la definizione del metodo abbia bisogno di sapere che sta ricevendo un parametro per riferimento, in quanto modifica il comportamento di modifica (ad es. Con = ). Si potrebbe obiettare, tuttavia, che il runtime non interessa (in tali linguaggi tipizzati staticamente, dove runtime-dispatch è nominalmente informato): deve solo ottenere questo valore dal chiamante al callee , non importa se si tratta di un riferimento o meno, che è una preoccupazione per il sito di chiamata e il target di chiamata.

Più liberamente, "call-site" potrebbe fare riferimento al codice che indica una chiamata e il codice "associato" che lo circonda (al contrario solo della "chiamata"). In C #, ad esempio, si potrebbe fare riferimento alla definizione di una variabile fittizia "a" un sito di chiamata, ad es. quando chiami un metodo TryParse :

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

Questo intero "blocco" potrebbe essere considerato parte del sito di chiamata. Lo considero un significato meno "preciso", ma questo non mi impedisce di usarlo.

    
risposta data 11.02.2018 - 12:06
fonte

Leggi altre domande sui tag