risposta

17

(Nota: darò per scontato che per "decodificare e spedizione" si intende un interprete basata su switch.)

La differenza tra uno switch-based e un interprete filettato il tempo di esecuzione è, in pratica, il numero di salti che vengono eseguiti.

In un interprete basato su switch, le istruzioni vengono decodificate in una posizione centrale e, in base al risultato della decodifica, viene eseguito un salto al pezzo di codice che gestisce l'istruzione decodificata. Una volta che quel pezzo di codice ha finito di interpretare l'istruzione, torna al codice di decodifica centralizzato, che procede con l'istruzione successiva. Ciò significa che (almeno) vengono eseguiti due salti per istruzione interpretata. Il seguente pezzo di codice C illustra ciò che una tale interprete potrebbe sembrare:

typedef enum { 
    add, /* ... */ 
} instruction_t; 

void interpret() { 
    static instruction_t program[] = { add /* ... */ }; 
    instruction_t* pc = program; 
    int* sp = ...; /* stack pointer */ 
    for (;;) { 
    switch (*pc++) { 
     case add: 
     sp[1] += sp[0]; 
     sp++; 
     break; 
     /* ... other instructions */ 
    } 
    } 
} 

In un interprete filettato, il codice di decodifica non è centralizzata, ma piuttosto duplicato alla fine di ogni pezzo di codice che gestisce un'istruzione. Ciò significa che una volta che un'interpretazione è stata interpretata, anziché tornare a un codice di decodifica centralizzato, l'interprete decodifica l'istruzione successiva e salta immediatamente ad essa. Implementare codice threaded in modo efficiente in ANSI-C non è realmente possibile, ma l'estensione "goto" di GCC funziona molto bene per questo. Ecco una versione filettata dell'interprete precedente:

void interpret() { 
    void* program[] = { &&l_add, /* ... */ }; 
    int* sp = ...; 
    void** pc = program; 
    goto **pc; /* jump to first instruction */ 
l_add: 
    sp[1] += sp[0]; 
    ++sp; 
    goto **(++pc); /* jump to next instruction */ 
    /* ... other instructions */ 
} 

Oltre al risparmio di un salto, tali interpreti filettati sono anche più efficiente perché il salto indiretta replicato (per l'istruzione successiva) può essere previsto meglio moderne CPU. Anton Ertl ha alcuni documenti interessanti su his home page, in particolare quello chiamato "La struttura e le prestazioni di interpreti efficienti", da cui sono stati adattati i pezzi di codice di cui sopra.