Bytekod

Bytecode (även kallad portabel kod eller p-kod [ citat behövs ] ) är en form av instruktionsuppsättning designad för effektiv exekvering av en mjukvarutolk . Till skillnad från mänskligt läsbar källkod är bytekoder kompakta numeriska koder, konstanter och referenser (normalt numeriska adresser) som kodar resultatet av kompilatorn som analyserar och utför semantisk analys av saker som typ, omfattning och kapslingsdjup för programobjekt.

Namnet bytecode härrör från instruktionsuppsättningar som har en- byte opkoder följt av valfria parametrar. Mellanrepresentationer som bytekod kan matas ut av programmeringsspråksimplementeringar för att underlätta tolkningen , eller så kan den användas för att minska beroendet av hårdvara och operativsystem genom att tillåta samma kod att köra plattformsoberoende på olika enheter. Bytekod kan ofta antingen exekveras direkt på en virtuell maskin (en p-kodmaskin , dvs tolk), eller så kan den kompileras ytterligare till maskinkod för bättre prestanda.

Eftersom bytekodinstruktioner bearbetas av mjukvara kan de vara godtyckligt komplexa, men är ändå ofta besläktade med traditionella hårdvaruinstruktioner: virtuella stackmaskiner är de vanligaste, men virtuella registermaskiner har också byggts. Olika delar kan ofta lagras i separata filer, liknande objektmoduler , men laddas dynamiskt under körning.

Avrättning

Ett bytekodprogram kan exekveras genom att tolka och direkt exekvera instruktionerna, en i taget. Den här typen av bytekodtolkare är mycket portabel. Vissa system, kallade dynamiska översättare, eller just-in-time (JIT) kompilatorer, översätter bytekod till maskinkod vid behov under körning . Detta gör den virtuella maskinen hårdvaruspecifik men förlorar inte bytekodens portabilitet. Till exempel Java- och Smalltalk -kod vanligtvis i bytekodformat, som vanligtvis sedan JIT kompileras för att översätta bytekoden till maskinkod innan exekvering. Detta introducerar en fördröjning innan ett program körs, när bytekoden kompileras till inbyggd maskinkod, men förbättrar exekveringshastigheten avsevärt jämfört med att tolka källkoden direkt, normalt med omkring en storleksordning (10x).

På grund av dess prestandafördelar kör många språkimplementationer idag ett program i två faser, först kompilerar källkoden till bytekod och skickar sedan bytekoden till den virtuella maskinen. Det finns bytekodbaserade virtuella maskiner av det här slaget för Java , Raku , Python , PHP , Tcl , mawk och Forth (men Forth kompileras sällan via bytekoder på detta sätt, och dess virtuella maskin är istället mer generisk). Implementeringen av Perl och Ruby 1.8 fungerar istället genom att gå en abstrakt syntaxträdrepresentation härledd från källkoden.

På senare tid har författarna till V8 och Dart ifrågasatt uppfattningen att mellanbytekod behövs för snabb och effektiv VM-implementering. Båda dessa språkimplementeringar gör för närvarande direkt JIT-kompilering från källkod till maskinkod utan någon bytekodförmedlare.

Exempel

    










 (  demontera  '  (  lambda  (  x  )  (  print  x  )))  ; demontering för (LAMBDA (X))   ; 2436F6DF: 850500000F22 TEST EAX, [#x220F0000] ;  no-arg-parsing ingångspunkt   ; E5: 8BD6 MOV EDX, ESI   ; E7: 8B05A8F63624 MOV EAX, [#x2436F6A8] ;  #<FDEFINITION-objekt för PRINT>   ; ED: B904000000 MOV ECX, 4   ; F2: FF7504 PUSH DWORD PTR [EBP+4]   ; F5: FF6005 JMP DWORD PTR [EAX+5]   ; F8: CC0A BREAK 10 ;  felfälla   ; FA: 02 BYTE #X02   ; FB: 18 BYTE #X18 ;  INVALID-ARG-COUNT-ERROR   ; FC: 4F BYTE #X4F ;  ECX  

Kompilerad kod kan analyseras och undersökas med hjälp av ett inbyggt verktyg för att felsöka bytekoden på låg nivå. Verktyget kan initieras från skalet, till exempel:

  




 >>>  importera  dis  # "dis" - Demonterare av Python-byte-kod till mnemonics.  >>>  dis  .  dis  (  'print("Hello, World!")'  )  1 0 LOAD_NAME 0 (print)  2 LOAD_CONST 0 ('Hej världen!')  4 CALL_FUNCTION 1  6 RETURN_VALUE 

Se även

Anteckningar