Baitkood

Baitkood (ingl. "bytecode", mõnikord ka p-kood, p-kood porditavast koodist, ingl. "portable code") on käsustiku vorm, mis on projekteeritud tõhusaks käivitamiseks tarkvaralise interpretaatori poolt. Erinevalt inimloetavast lähtekoodist koosneb baitkood kompaktsetest numberkoodidest, konstantidest ja viidetest (milleks harilikult on numbrilised aadressid), mis kodeerivad kompilaatori parsimise tulemuse ja teostavad semantilist analüüsi programmiobjektide tüübile, skoobile ja pesastamise sügavusele. Tehnilisest vaatenurgast on baitkood lähtekoodist genereeritud ja madala taseme masinast sõltumatu kood.
Paljud kaasaegsed programmeerimiskeeled, eriti kompileeritavad, kasutavad baitkoodi kompilaatori töö hõlbustamiseks ja kiirendamiseks.
Vormilt sarnaneb baitkood masinakoodiga, kuid see on mõeldud täitmiseks mitte reaalse protsessori, vaid virtuaalmasina poolt. Tavaliselt vastava programmeerimiskeele tõlk (mõnikord täiendab seda JIT- või AOT-kompilaatoriga) toimib virtuaalmasinana. Baitkoodi ja seda teostavate virtuaalmasinate spetsifikatsioonid võivad eri keeltes oluliselt erineda: sageli koosneb baitkood juhendist pinupõhise virtuaalmasina jaoks, kuid saab kasutada ka registripõhiseid masinaid. Siiski on enamus baitkoodide juhendeid tavaliselt võrdsed ühe või mitme assembleri käsuga.
Baitkoodi on nime saanud sellest, et iga opkood on traditsiooniliselt ühe baidi suurune. Iga käsk on tavaliselt ühebaidine opcode (0–255), millele võivad järgneda parameetrid, näiteks registrinumber või mäluaadress.
Täitmine.
Tavaliselt baitkoodi programmi täidab baitkoodi interpretaator. Baidikoodi eelis on suurem efektiivsus ja teisaldatavus, st sama baitkood saadakse teostada erinevatel platvormidel ja arhitektuuridel, mille jaoks interpretaator on rakendatud. Otseselt interpreteerivad keeled pakuvad samasugust eelist, kuid tavaliselt baitkood on vähem abstraktne ja kompaktsem kui lähtekood, baitkoodi interpreteerimise tõhusus on tavaliselt kõrgem kui lähtekoodi või abstraktne interpretatsiooni tõlgenduse puhas interpreteerimine. Lisaks on baitkoodi interpretaator sageli lihtsam kui lähtekoodi interpretaator ja seda on lihtsam teisele riistvaraplatvormile üle kanda.
Virtuaalarvutite kõrgtehnoloogilistes rakendustes saab kasutada interpretaatori ja JIT-kompilaatori kombinatsiooni, mis programmitöö käigus tõlgib sageli kasutatavaid baitekoodi fragmente masina koodiks, rakendades erinevaid optimeeringuid. JIT-i kompileerimise asemel võib enne täitmist kasutada AOT-kompilaatorit, tõlkides baitkoodi masina koodiks.
Samal ajal on võimalik luua protsessoreid, mille jaoks antud baitkood on otse masina kood (sellised eksperimentaalsed protsessorid loodi näiteks Java ja Forth keelte jaoks).
Ajalugu.
Esimesed baitkoodi kasutavad süsteemid olid BCPL-i O-kood (1960ndad), Smalltalk (1976), SIL (Süsteemi rakendamise keel) Snobol-4 jaoks (1967), p-kood (p-kood, 1970, koos Niklaus Wirthiga), Pascal programmeerimiskeele porditavatele kompilaatoritele.
P-koodi variante kasutati laialdaselt Pascali keele mitmesugustes rakendustes, näiteks UCSD p-süsteemis (UCSD Pascal).
Rakendus.
Baitkoodi interpreteeritud keeled on Perl, PHP (näiteks Zend Engine), Ruby (alates versioonist 1.9), Python, Erlang ja paljud teised.
Baitkoodi kasutavad laialdased platvormid:
Clipper-kompilaator loob käivitatava faili, mis sisaldab programmi lähtekoodist tõlgitud baitekoodi ja seda baitekoodi täitvat virtuaalse masina.
Tavaliselt Java programmid kompileeritakse klassifailidesse (class-fail), mis sisaldavad Java baitkoodi. Need universaalsed failid kantakse üle erinevatesse sihtmärkmehhanismidesse.
Visual Basici varajastes rakendustes (kuni versioon 6) kasutati kõrgetasemelist p-koodi
DBMSis kasutati kõrgetasemelisi p-koode ja baitkoode, mõned BASICi ja Pascali rakendused.
Sun Microsystemsi standardse Open Firmware Openloaderi puhul esindab baitkood Forth operaatorit.
Näited.
Python.
Kood:
»&gt; print("Hello, World!")
Hello, World!
Baitkood:
»&gt; import dis # impordime mooduli "dis" - Disassembler of Python byte code into mnemonics.
»&gt; dis.dis('print("Hello, World!")')
 1 0 LOAD_NAME 0 (print)
 2 LOAD_CONST 0 ('Hello, World!')
 4 CALL_FUNCTION 1
 6 RETURN_VALUE
Java.
Kood:
outer:
for (int i = 2; i &lt; 1000; i++) {
 for (int j = 2; j &lt; i; j++) {
 if (i% j == 0)
 continue outer;
 System.out.println (i);
Baitkood:
 0: iconst_2
 1: istore_1
 2: iload_1
 3: sipush 1000
 6: if_icmpge 44
 9: iconst_2
 10: istore_2
 11: iload_2
 12: iload_1
 13: if_icmpge 31
 16: iload_1
 17: iload_2
 18: irem
 19: ifne 25
 22: goto 38
 25: iinc 2, 1
 28: goto 11
 31: getstatic #84; //Field java/lang/System.out:Ljava/io/PrintStream;
 34: iload_1
 35: invokevirtual #85; //Method java/io/PrintStream.println:(I)V
 38: iinc 1, 1
 41: goto 2
 44: return
Arvustus.
Traditsiooniliselt on baitkood projekteeritud pinupõhiste virtuaalmasinate stiilis, mis lihtsustab genereerimist (!?!?), võimaldab kasutada lihtsamat ja kompaktsemat baitkoodi kodeeringut, lihtsustada interpretaatorit ja vähendada ühe baitkoodi käsu täitmiseks vajaliku masinkäskude arvu. Teiselt poolt sellised baitkoodivariandid sisaldavad antud programmiks rohkem juhiseid kui registripõhiste virtuaalmasinate baitkoodid, mille tõttu interpretaator peab tegema rohkem kaudse väärtuse alusel hargnemisi, mille puhul hargnemiste ennustamine ei toimi hästi. Registripõhiste virtuaalmasinate baitkoodil on veidi suurem masina koodide arv, kuid hargnemiste arv on umbes kaks korda väiksem kui stopp-baitkood(?) ja interpretaator on kümneid protsente kiirem. Samuti on pinupõhiste masinate baitkood optimeerimise jaoks keerulisem (viited muutuvad kaudseteks, seotud käsud ei ole rühmitatud, väljendid jagatakse mitme põhiploki vahel) ja nõutakse korstna kasutamise õigsuse kontrollimist
Vead kontrollimises stack-masinate baitkoodi tõid kaasa hulga üliohtlike haavatavuste tekkimise, eriti kümneid AVM2 virtuaalmasinas, mida Adobe Flashis kasutati ActionScript ja mitme varasema populaarse Java-süsteemiga (JVM). )
2000. aastate lõpus ja 2010. aasta alguses kahtlesid V8-kompilaatorite autorid (JavaScripti keel, mida sageli rakendatakse baitkoodi kaudu)) ja Dart, et kiire ja tõhusa virtuaalse masina jaoks on vaja vaheprotseduuride baitkoode. Nendes projektides oli realiseeritud otsene JIT-i koostamine (koostamine käivitusajal) lähtekoodist otse masina koodis.