Codul threaded este una dintre modalitățile de implementare a unei mașini virtuale intermediare la interpretarea limbajelor de programare (împreună cu bytecode ). Ocazional, termenul de cod reticulat este de asemenea întâlnit în literatură .
Reprezentarea principală a programului atunci când se utilizează codul threaded este o matrice de apeluri subrutine . Implementarea codului threaded, modul în care aceste apeluri sunt stocate pot fi diferite. Acest cod poate fi procesat de un interpret (care a devenit cunoscut sub numele de interpret de adrese ) sau poate fi o simplă secvență de instrucțiuni de mașină care apelează o subrutină. Unele set de subrutine de bază ale unei mașini virtuale care utilizează cod threaded sunt implementate ca subrutine scrise în codul de mașină obișnuit .
Codul threaded este cel mai frecvent cunoscut ca o tehnică folosită în implementarea Forth . Cu toate acestea, a fost folosit și în implementarea limbajului de programare B (precursorul lui C ). De asemenea, este uneori folosit în implementarea BASIC , COBOL și a altor limbaje de programare.
Codul cusut este relativ compact în comparație cu codul mașinii. Acest avantaj vine cu prețul unei încetiniri. Cu toate acestea, aici intră în joc un efect sinergic - uneori un cod compact este mai mic și vizibil mai rapid decât un cod obișnuit, fără fire [1] . Un program suficient de mic pentru a se potrivi complet în RAM va rula mai repede decât un program care utilizează memorie virtuală, care implică paginarea de pe hard disk. În mod similar, un program care se încadrează în întregime în memoria cache a procesorului va rula mai repede .
Acest tip de cod fir nu este în esență diferit de codul mașinii . Aceasta este o secvență de apeluri către subrutine deja compilate.
Programul arată astfel:
callSub1; callSub2; callSub3;
Acest cod este obținut din subrutină dacă apelurile la apel sunt eliminate din cod. În corpul codului rămân doar adresele subrutinelor. Apelarea subrutinelor se realizează folosind cel mai simplu interpret de adrese, care ocupă mai multe instrucțiuni de mașină (în unele arhitecturi de procesor, una).
apel interpret; AdrSub1; AdrSub2; ... adresa EXIT; ... ... Interpretator: cod mașină, NEXT ... Sub...: cod mașină, NEXT ... EXIT: cod mașină, NEXTÎn codul cu filet drept, orice definiție (de ex. Sub) începe cu codul mașină. Interpretul trebuie să stocheze în stiva de returnare valoarea trecută a contorului de instrucțiuni (acesta nu este PC sau IP, ci altul care se deplasează prin codul Forth) și să-și facă adresa de retur actuală. Va deveni acum noul indicator către codul Forth. Unele versiuni Intel x86 folosesc registrul SI. La citirea datelor la o adresă indirectă din acest registru, valoarea acesteia se schimbă automat.
NEXT este secvența folosită în loc de return. Dacă completăm Sub1, atunci NEXT accesează contorul de instrucțiuni Forth, îl schimbă la dimensiunea codului, iar în pasul următor, prima instrucțiune de mașină din Sub2 este deja executată. Viteza de tranziție nu este mai rea decât cea a unei perechi de comenzi return-call. Dar tranziția NEXT într-un procesor specializat poate fi executată ca o singură instrucțiune.
EXIT - restabilește valoarea anterioară a contorului programului și sare la adresa corespunzătoare.
Diferă de codul direct threaded prin faptul că corpul codului nu începe cu un apel către interpret, ci cu adresa unde se află interpretul.
AdrInterpretator; AdrSub1; AdrSub2; ... adresa EXIT; ... ... Interpretator: Adresă cod mașină, cod mașină, NEXT ... Sub...: adresa codului mașinii, codul mașinii, NEXT ... EXIT: Adresă cod mașină, cod mașină, NEXTPoate fi folosit, de exemplu, pentru a reduce dimensiunea codului atunci când acesta este de importanță critică. Poate fi atât directă, cât și indirectă. În loc de adrese directe ale subrutinelor și codurilor, folosește pliurile acestora, care, în general, sunt mai scurte decât aceste adrese. Folosind coduri de 2 octeți, puteți utiliza un spațiu de adrese de peste 64 de kiloocteți.
Deci, dacă știm că codul și datele sunt aliniate în raport cu dimensiunea unui segment (de exemplu, 16 octeți), putem folosi adresa fizică împărțită la 16 ca adresă pliată.
În unele cazuri, un tabel de adrese poate fi folosit pentru pliere. Codul cusut este poziția adresei în tabel. Interpretul citește acest cod din tabel și sare la adresa corespunzătoare.
Bytecode poate fi considerat ca un caz special de cod pliat cu un tabel de adrese.