Hoe de ActionScript-virtuele machine werkt

Als je betrokken bent bij de ontwikkeling van AS3, heb je misschien gehoord van een virtuele machine die in de Flash Player leeft of van de zogenaamde bytecode waar je code in wordt omgezet. Maar wat zijn ze precies??

Een belangrijk onderdeel van de Flash Player is de AVM - de ActionScript-virtuele machine. Wanneer u uw AS3-code compileert, wordt deze omgezet in een binaire instructieset, bytecode genaamd, die is ingesloten in de geproduceerde SWF. Wanneer een gebruiker de SWF in de Flash Player laadt, parseert de AVM de bytecode en voert deze stap voor stap uit.

Laten we het proces een beetje gedetailleerder bekijken: bekijk de volgende verklaring en stel je voor dat we het willen uitvoeren (bereken het resultaat en wijs het toe aan "foo"):

foo = 2 + 3 * 4;

Vanuit menselijk oogpunt betekent deze regel "Vermenigvuldig 3 bij 4, voeg 2 toe aan het resultaat en wijs dat toe aan een variabele met de naam foo".

Aan de andere kant, als een computer deze regel leest, wordt deze opgeslagen als "teken f, gevolgd door teken o, gevolgd door teken o, gevolgd door tekenruimte, gevolgd door teken gelijken, gevolgd door?." Enzovoorts. In deze toestand is deze informatie vrij nutteloos en moeten er aanvullende stappen worden ondernomen om de uitspraak om te zetten in iets dat een machine kan uitvoeren. Wat we eigenlijk moeten doen, is de broncode compileren.


The Compiler

Zoals ik eerder heb opgemerkt, is de bovenstaande verklaring een ruwe broncode, een verzameling tekens die niets betekenen voor een computer. Om bruikbare informatie te verkrijgen, moeten we de code door een paar procedures leiden. Eerst moeten we de stroom karakters in woorden veranderen en ten tweede de woorden in zinnen omzetten.

De eerste stap om de tekens in woorden om te zetten, wordt gedaan door een tokenizer die in feite lexicale analyse van de broncode uitvoert. Het loopt over de karakters en groepeert ze in reeksen "tokens" (en het bepaalt ook hun type-identificaties, operatoren, constanten?). Nadat de tokenizer (het wordt ook een lexer BTW genoemd) zijn taak voltooit, krijgen we een array die als volgt kan worden geïllustreerd:

[Identifier foo] [Operator is gelijk aan] [Geheel getal 2] [Operator plus] [Geheel getal 3] [Operator vermenigvuldigd] [Geheel getal 4]

Dit is een structuur op een hoger niveau die 'woorden' bevat in plaats van de onbewerkte tekens.

De resulterende tokens worden in een parser ingevoerd. Het voert een semantische analyse uit van de tokens en assembleert deze tot machine-instructies. In eenvoudigere woorden construeert het zinnen uit de woorden (tokens) en maakt het daaruit logisch (dat wil zeggen verzamelt instructies uit deze woorden). Bijvoorbeeld als de parser een statement 2 + 3 krijgt; i ++; als tokens moet de parser eerst de tokens in "zinnen" (2 + 3 en i ++) scheiden en ze dan eigenlijk begrijpen (de eerste is add-bewerking en de tweede is een toename). Nadat we de instructie hebben begrepen, kunnen we eigenlijk instructies uit de invoer naar de machine verzamelen.

Na het ontleden van de tokens van onze string krijgen we de volgende instructies:

push 2 push 3 push 4 vermenigvuldig toevoegen assign "foo"

Dit zijn instructies die een computer kan uitvoeren. Comprimeer het naar een binair formaat en je hebt bytecode. Bytecode is een lijst met instructies die aangeven dat een machine erg goed is in het verwerken en wanneer ze in volgorde worden verwerkt, de gewenste resultaten opleveren.


De tolk

Nadat we de broncode hebben gecompileerd naar bytecode, kunnen we deze met een virtuele machine uitvoeren. De VM is software die de bytecode één instructie tegelijk uitvoert, dus laten we gewoon de interpretatie van onze verklaring eens doorlopen:

  1. druk op 2 -- Het commando is om nummer 2 in de stapel te duwen. De VM houdt tijdens de uitvoering een stapel bij waarop de commando's kunnen werken, dat wil zeggen om waarden in en uit te schakelen (http://en.wikipedia.org/wiki/Stack_(data_structure)). Momenteel ziet de stapel er als volgt uit: [2]
  2. druk op 3 -- druk een ander geheel getal in de stapel. Nu lijkt het op [2, 3];
  3. druk op 4 -- druk nog een ander geheel getal in de stapel. Nu lijkt het [2, 3, 4];
  4. vermenigvuldigen -- deze opdracht knalt 2 waarden uit de stapel, vermenigvuldigt ze en drukt het resultaat terug naar de stapel. Het werpt de waarden 3 en 4 (die zich momenteel op de stapel bevinden), vermenigvuldigt ze en duwt de resulterende 12 naar de stapel. Het beïnvloedt de stapel om er uit te zien [2, 12];
  5. toevoegen -- je hebt het waarschijnlijk al geraden: de opdracht pop 12 en 2 van de stapel, voegt ze toe en duwt de resulterende 14 in de stapel. Nu zijn er nog maar 14 in de stapel.
  6. "foo" toewijzen -- Met deze opdracht wordt een waarde uit de stapel verwijderd en toegewezen aan een variabele met de naam foo. Dus de variabele foo bevat nu de waarde 14 en de stapel is leeg.

Dat is het! Dit is een voorbeeld van een uiterst eenvoudige verklaring uitgevoerd van een uiterst eenvoudige virtuele machine. Laten we een iets gecompliceerder voorbeeld bekijken:

bar = 12 / (4 + 2) - (6 - 9) * 3

Dit kan compileren naar (ik zeg "kan" omdat er verschillende manieren zijn om de verklaring te compileren):

druk op 12 druk op 4 druk op 2 toevoegen verdelen druk op 6 druk op 9 aftrekken druk op 3 vermenigvuldig aftrekken toewijzen "bar"

Dit zal worden geïnterpreteerd als:

  1. De eerste 3 pogingen worden toegevoegd aan de stapel: [12, 4, 2]
  2. toevoegen -- zal de 2 waarden bovenaan de stapel optellen: [12, 6]
  3. verdelen -- zal 6 laten springen, dan pop 12, 12 delen door 6 en het resultaat naar de stapel duwen: [2]
  4. De volgende 2 commando's zullen gehele getallen in de stapel duwen: [2, 6, 9]
  5. aftrekken -- zal de 2 getallen boven aan de stapel aftrekken. Zal 9 worden, dan 6, dan 6 van 9 aftrekken en het resultaat naar de stapel schuiven: [2, -3]
  6. Een ander geheel getal wordt naar de stapel geduwd: [2, -3, 3]
  7. vermenigvuldigen -- zal knallen en vermenigvuldigen de 2 nummers aan de bovenkant van de stapel. -9, dat 3 keer -3 is, wordt teruggeduwd naar de stapel: [2, -9]
  8. aftrekken -- zal -9 van 2 aftrekken en het resultaat naar de stapel duwen: [11]
  9. toewijzen -- zal pop 11 en toewijzen aan een variabele met de naam "bar". Stack is nu leeg.

Het resultaat wordt nu opgeslagen in een variabele met de naam "balk" en het is 11. Yay!


Conclusie

Dat is de meest elementaire informatie over een VM, het kan van pas komen wanneer je wat low-level Flash Player-dingen begint te leren. De VM binnen de Flash Player is natuurlijk veel complexer, maar de basis is hetzelfde als in het voorbeeld hierboven.

Als u meer wilt weten over de ActionScript Virtual Machine, kunt u dit PDF-document van Adobe bekijken. Bedankt voor het lezen!