Stabel maskine - Stack machine

Inden for datalogi , computerteknik og programmeringssprogsimplementeringer er en stakemaskine en computerprocessor eller en virtuel maskine , hvor den primære interaktion flytter kortvarige midlertidige værdier til og fra en nedadgående stak . I tilfælde af en hardware -processor bruges en hardware -stak . Brugen af ​​en stak reducerer betydeligt det nødvendige antal processorregistre . Stackmaskiner forlænger push-down-automat med yderligere belastnings-/butiksoperationer eller flere stakke og er derfor Turing-komplette .

Design

De fleste eller alle stabelmaskininstruktioner antager, at operander kommer fra stakken, og resultater placeres i stakken. Stakken rummer let mere end to input eller mere end et resultat, så et stort sæt operationer kan beregnes. I stack maskinkode (undertiden kaldet p-kode ) vil instruktioner ofte kun have en opcode, der kommanderer en operation, uden yderligere felter, der identificerer en konstant, register eller hukommelsescelle, kendt som et nuladresseformat . Dette forenkler i høj grad instruktionens afkodning. Filialer, indlæsning med det samme og instruktioner til indlæsning/lagring kræver et argumentfelt, men stabelmaskiner arrangerer ofte, at de hyppige tilfælde af disse stadig passer sammen med opcode i en kompakt gruppe bits. Valget af operander fra tidligere resultater sker implicit ved at bestille instruktionerne. Nogle instruktionssæt til stakmaskiner er beregnet til fortolkning af en virtuel maskine i stedet for at køre hardware direkte.

Hele tal konstante operander skubbes af Pusheller Load Immediateinstruktioner. Hukommelse er ofte tilgængelig ved separat Loadeller Storeinstruktioner, der indeholder en hukommelsesadresse eller beregning af adressen ud fra værdier i stakken. Alle praktiske stakmaskiner har varianter af opslagskoder til belastningsopbevaring for at få adgang til lokale variabler og formelle parametre uden eksplicitte adresseberegninger. Dette kan være ved forskydninger fra den aktuelle top-of-stack adresse eller ved forskydninger fra et stabilt frame-base-register.

Den instruktionssæt udfører de fleste ALU aktioner med postfix ( omvendt polsk notation ) operationer, at arbejdet kun på ekspressionen stakken, ikke på dataregistre eller vigtigste hukommelsesceller. Dette kan være meget praktisk til udførelse af sprog på højt niveau, fordi de fleste aritmetiske udtryk let kan oversættes til postfix-notation.

Binært syntakstræ for udtrykket A *( B - C ) + ( D + E )

Betragt for eksempel udtrykket A * ( B - C ) + ( D + E ), skrevet i omvendt polsk notation som A B C - * D E + +. Kompilering og kørsel af dette på en simpel imaginær stakmaskine ville have formen:

                 # stack contents (leftmost = top = most recent):
 push A          #           A
 push B          #     B     A
 push C          # C   B     A
 subtract        #     B-C   A
 multiply        #           A*(B-C)
 push D          #     D     A*(B-C)
 push E          # E   D     A*(B-C)
 add             #     D+E   A*(B-C)
 add             #           A*(B-C)+(D+E)

De aritmetiske operationer 'subtraherer', 'multiplicerer' og 'add' virker på stakens to øverste operander. Computeren tager begge operander fra stakens øverste (seneste) værdier. Computeren erstatter disse to værdier med den beregnede forskel, sum eller produkt. Med andre ord "sprænges" instruktionens operander af stakken, og dens resultat (er) "skubbes" tilbage på stakken, klar til den næste instruktion.

Stabelmaskiner kan have deres udtryksstabel og deres opkald-retur-stak adskilt eller som en integreret struktur. Hvis de er adskilt, kan stabelmaskinens instruktioner rørlægges med færre interaktioner og mindre designkompleksitet, så det vil normalt køre hurtigere.

Optimering af kompileret stakkode er ganske mulig. Back-end-optimering af kompilatoroutput har vist sig at forbedre kode og potentielt ydeevne betydeligt, mens global optimering inden for selve kompilatoren opnår yderligere gevinster.

Stack opbevaring

Nogle stakmaskiner har en stak af begrænset størrelse, implementeret som en registerfil. ALU får adgang til dette med et indeks. En stor registerfil bruger mange transistorer, og derfor er denne metode kun egnet til små systemer. Nogle få maskiner har både en udtrykstak i hukommelsen og en separat registerstabel. I dette tilfælde kan software eller en afbrydelse flytte data mellem dem. Nogle maskiner har en stak med ubegrænset størrelse, implementeret som en matrix i RAM, som cachelagres af et antal "top of stack" -adresseregistre for at reducere hukommelsesadgang. Bortset fra eksplicitte instruktioner om "indlæsning fra hukommelse" er rækkefølgen af ​​operandbrug identisk med rækkefølgen af ​​operanderne i datastakken, så fremragende forhåndshentning kan let udføres.

Overvej X+1. Det kompilerer til Load X; Load 1; Add. Med en stak, der er gemt fuldstændigt i RAM, betyder dette implicit at skrive og læse om in-memory-stakken:

  • Indlæs X, skub til hukommelsen
  • Indlæs 1, skub til hukommelsen
  • Pop 2 værdier fra hukommelsen, tilføj og skub resultatet til hukommelsen

for i alt 5 datacache -referencer.

Det næste trin op fra dette er en stakmaskine eller tolk med et enkelt top-of-stack-register. Ovenstående kode gør derefter:

  • Indlæs X i tomt TOS -register (hvis hardware maskine) eller Skub TOS -register til hukommelse, Indlæs X i TOS -register (hvis tolk)
  • Skub TOS -register til hukommelse, indlæs 1 i TOS -register
  • Pop venstre operand fra hukommelsen, tilføj til TOS -registeret og lad den være der

for i alt 5 datacache-referencer, worst-case. Generelt sporer tolke ikke tomhed, fordi de ikke behøver-noget under stakmarkøren er en ikke-tom værdi, og TOS-cacheregisteret holdes altid varmt. Typiske Java-tolke buffer imidlertid ikke top-of-stack på denne måde, fordi programmet og stakken har en blanding af korte og brede dataværdier.

Hvis den hardwired stack-maskine har 2 eller flere top-stack-registre eller en registerfil, undgås al hukommelsesadgang i dette eksempel, og der er kun 1 datacachecyklus.

Historie og implementeringer

Beskrivelse af en sådan metode, der kun kræver, at to værdier ad gangen opbevares i registre, med et begrænset sæt foruddefinerede operander, der kunne udvides ved definition af yderligere operander, funktioner og underprogrammer, blev først givet på konferencen af Robert S. Barton i 1961.

Kommercielle stakmaskiner

Eksempler på stack instruktionssæt, der direkte udføres i hardware, inkluderer

  • F18A-arkitekturen for den 144-processor GA144-chip fra GreenArrays, Inc.
  • den Z4 computeren ved Konrad Zuse .
  • den Burroughs store systemer arkitektur (siden 1961)
  • den Xerox Mælkebøtte introducerede april 27, 1981 udnyttet en stak maskine arkitektur for at spare hukommelse.
  • den engelske elektriske KDF9 maskine. KDF9 blev første gang leveret i 1964 og havde en 19-dyb pushdown-stak med aritmetiske registre og en 17-dyb stak til underrutinereturadresser
  • Den Collins Radio Collins Adaptive Processing System minicomputer (CAPS, siden 1969) og Rockwell Collins Advanced Architecture Mikroprocessor (AAMP siden 1981).
  • Den UCSD Pascal p-maskine (som Pascal mikromaskinen og mange andre) støttede en komplet elev programmeringsmiljø på tidlige 8-bit mikroprocessorer med dårlige instruktionssæt og lidt RAM, ved at indsamle til en virtuel stak maskine.
  • MU5 og ICL 2900 -serien . Hybride stak- og akkumulatormaskiner. Akkumulatorregistret bufferlagrede hukommelsesstakens øverste dataværdi. Varianter af belastning og lagring af opcoder, der kontrolleres, når dette register blev spildt til hukommelsesstakken eller genindlæst derfra.
  • HP 3000 (Classic, ikke PA-RISC)
  • Tandemcomputere T/16. Ligesom HP 3000, bortset fra at kompilatorer, ikke mikrokode, kontrolleres, når registerstakken spildte til hukommelsesstakken eller blev genopfyldt fra hukommelsesstakken.
  • den Atmel MARC4 microcontroller
  • Flere "Forth chips" såsom RTX2000, RTX2010 , F21 og PSC1000
  • Den Setun Tre computer udføres afbalanceret ternære ved hjælp af en stak.
  • 4 -stacks processor fra Bernd Paysan har fire stakke.
  • Patriot Scientific's Ignite -stakmaskine designet af Charles H. Moore har et førende benchmark for funktionel densitet .
  • Saab Ericsson Space Thor strålingshærdet mikroprocessor
  • Inmos -transducere .
  • ZPU En fysisk lille CPU designet til at overvåge FPGA- systemer.
  • Nogle tekniske håndholdte lommeregnere bruger omvendt polsk notation i deres tastaturgrænseflade i stedet for at have parentesetaster. Dette er en form for stakemaskine. Plus-tasten er afhængig af, at dens to operander allerede befinder sig på de korrekte øverste positioner i den bruger-synlige stak.

Virtuelle stakmaskiner

Eksempler på virtuelle stakmaskiner fortolket i software:

Hybride maskiner

(Disse bør ikke forveksles med hybridcomputere, der kombinerer både digitale og analoge funktioner, f.eks. En ellers digital computer, der får adgang til analog multiplikation eller løsning af differentialligninger ved hukommelseskortlægning og konvertering til og fra en analog enheds input og output.)

Pure stack -maskiner er ret ineffektive til procedurer, der har adgang til flere felter fra det samme objekt. Stakkemaskinens kode skal genindlæse objektmarkøren for hver markør+forskydningsberegning. En almindelig løsning på dette er at tilføje nogle registermaskinfunktioner til stakmaskinen: en synlig registerfil dedikeret til at holde adresser og instruktioner i registerstil til at udføre belastninger og enkle adresseberegninger. Det er ualmindeligt, at registre er fuldt ud generelle formål, for så er der ingen stærk grund til at have en udtryksstabel og postfix -instruktioner.

En anden almindelig hybrid er at starte med en registermaskinarkitektur og tilføje en anden hukommelsesadressetilstand, der efterligner push- eller pop -operationerne på stakemaskiner: 'memaddress = reg; reg += instr.displ '. Dette blev først brugt i DEC 's PDP-11 minicomputer. Denne funktion blev videreført i VAX -computere og i Motorola 6800 og M68000 mikroprocessorer. Dette tillod brug af enklere stakmetoder i tidlige kompilatorer. Det understøttede også effektivt virtuelle maskiner ved hjælp af stakkeltolke eller trådkode . Denne funktion hjalp imidlertid ikke registreringsmaskinens egen kode med at blive lige så kompakt som ren stakmaskinkode. Udførelseshastigheden var også mindre end ved kompilering af godt til registerarkitekturen. Det er hurtigere at ændre top-of-stack-markøren kun lejlighedsvis (en gang pr. Opkald eller retur) i stedet for konstant at trappe det op og ned gennem hvert programudsagn, og det er endnu hurtigere at undgå hukommelsesreferencer helt.

For nylig har såkaldte anden generations stakmaskiner vedtaget en dedikeret samling af registre, der skal fungere som adresseregistre, og udlader opgaven med hukommelsesadressering fra datastakken. For eksempel er MuP21 afhængig af et register kaldet "A", mens de nyere GreenArrays -processorer er afhængige af to registre: A og B.

Intel x86-familien af ​​mikroprocessorer har et registret (akkumulator) instruktionssæt til de fleste operationer, men brug stakkeinstruktioner til dets x87 , Intel 8087 floating point-aritmetik, der går tilbage til iAPX87 (8087) coprocessoren til 8086 og 8088. Det er, er der ingen programmeringsbare flydende punktregistre, men kun en 80-bit bred, 8 dyb stak. X87 er stærkt afhængig af x86 -CPU'en for at få hjælp til at udføre sine operationer.

Computere, der bruger opkaldsstakke og stabelrammer

De fleste nuværende computere (af enhver instruktionssætstil) og de fleste kompilatorer bruger en stor call-return-stak i hukommelsen til at organisere de kortvarige lokale variabler og returlinks til alle aktive procedurer eller funktioner i øjeblikket. Hvert indlejret opkald opretter en ny stakramme i hukommelsen, der fortsætter, indtil det opkald er fuldført. Denne call-return-stak kan muligvis styres fuldstændigt af hardwaren via specialiserede adresseregistre og særlige adressetilstande i vejledningen. Eller det kan bare være et sæt konventioner efterfulgt af kompilatorerne ved hjælp af generiske registre og register+offset adressetilstande. Eller det kan være noget imellem.

Da denne teknik nu er næsten universel, selv på registermaskiner, er det ikke nyttigt at betegne alle disse maskiner som stabelmaskiner. Dette udtryk er almindeligt forbeholdt maskiner, der også bruger en udtryksstabel og kun stak-aritmetiske instruktioner til at evaluere stykkerne i en enkelt sætning.

Computere giver normalt direkte, effektiv adgang til programmets globale variabler og til de lokale variabler kun for den nuværende inderste procedure eller funktion, den øverste stabelramme. 'Up level' adressering af indholdet af opkalders stakkrammer er normalt ikke nødvendig og understøttes ikke direkte af hardwaren. Om nødvendigt understøtter kompilatorer dette ved at sende rammepunkter ind som yderligere, skjulte parametre.

Nogle Burroughs-stakmaskiner understøtter refs på højeste niveau direkte i hardwaren med specialiserede adressetilstande og en særlig 'display'-registerfil, der indeholder rammeadresserne for alle ydre omfang. Ingen efterfølgende computerlinjer har gjort dette inden for hardware. Da Niklaus Wirth udviklede den første Pascal -kompilator til CDC 6000 , fandt han ud af, at det generelt var hurtigere at passere rammepegene som en kæde, frem for konstant at opdatere komplette arrays af rammepunkter. Denne softwaremetode tilføjer heller ingen overhead til almindelige sprog som C, der mangler ref-niveau på højt niveau.

De samme Burroughs -maskiner understøttede også indlejring af opgaver eller tråde. Opgaven og dens skaber deler de stabelrammer, der fandtes på tidspunktet for opgaveoprettelsen, men ikke skaberens efterfølgende rammer eller opgavens egne rammer. Dette blev understøttet af en kaktusstak , hvis layoutdiagram lignede bagagerummet og armene på en Saguaro -kaktus. Hver opgave havde sit eget hukommelsessegment, der holder sin stak og de rammer, den ejer. Bunden af ​​denne stak er knyttet til midten af ​​dens skabers stak. I maskiner med et konventionelt fladt adresserum ville skaberstakken og opgavestakene være separate bunkeobjekter i en bunke.

I nogle programmeringssprog er datamiljøerne i det ydre omfang ikke altid indlejret i tid. Disse sprog organiserer deres procedure 'aktiveringsposter' som separate bunkeobjekter i stedet for som stabelrammer, der er knyttet til en lineær stak.

På enkle sprog som Forth, der mangler lokale variabler og navngivning af parametre, ville stakkrammer ikke indeholde andet end returfilialadresser og overordnet rammehåndtering. Så deres returstabel indeholder bare returadresser frem for rammer. Returstakken er adskilt fra dataværdiestakken for at forbedre strømmen af ​​opkaldsopsætning og -returer.

Sammenligning med registermaskiner

Stabelmaskiner sammenlignes ofte med registermaskiner , der har værdier i en række registre . Registermaskiner kan gemme staklignende strukturer i dette array, men en registermaskine har instruktioner, der omgår stakgrænsefladen. Registreringsmaskiner udfører rutinemæssigt bedre resultater end stakmaskiner, og stakemaskiner er forblevet en nichespiller inden for hardwaresystemer. Men stakmaskiner bruges ofte til implementering af virtuelle maskiner på grund af deres enkelhed og lette implementering.

Instruktioner

Stackmaskiner har højere kodetæthed . I modsætning til almindelige stabelmaskininstruktioner, der let kan passe i 6 bits eller mindre, kræver registermaskiner to eller tre registernummerfelter pr. ALU-instruktion for at vælge operander; de tætteste registermaskiner har i gennemsnit ca. 16 bit pr. instruktion plus operanderne. Registreringsmaskiner bruger også et bredere offsetfelt til oplagskoder med lastlager. En stakmaskines kompakte kode passer naturligvis til flere instruktioner i cachen og kan derfor opnå bedre cache -effektivitet, reducere hukommelsesomkostninger eller tillade hurtigere hukommelsessystemer til en given pris. Derudover er den fleste stabel-maskine instruktion meget enkel, lavet af kun et opcode felt eller et operand felt. Således kræver stakmaskiner meget få elektroniske ressourcer til at afkode hver instruktion.

Et program skal udføre flere instruktioner, når det kompileres til en stakmaskine, end når det kompileres til en registermaskine eller hukommelse til hukommelsesmaskine. Hver variabel belastning eller konstant kræver sin egen separate Load -instruktion i stedet for at være bundtet i instruktionen, der bruger denne værdi. De adskilte instruktioner kan være enkle og hurtigere at køre, men det samlede antal instruktioner er stadig højere.

De fleste registolke angiver deres registre efter nummer. Men en værtsmaskines registre kan ikke tilgås i et indekseret array, så der tildeles en hukommelsesmatrix til virtuelle registre. Derfor skal instruktionerne fra en registertolker bruge hukommelse til at overføre genererede data til den næste instruktion. Dette tvinger registerfortolkere til at være meget langsommere på mikroprocessorer fremstillet med en fin procesregel (dvs. hurtigere transistorer uden at forbedre kredsløbshastigheder, såsom Haswell x86). Disse kræver flere ure til hukommelsesadgang, men kun et ur til registeradgang. I tilfælde af en stakmaskine med et dataforretningskredsløb i stedet for en registerfil, kan stakfortolke tildele værtsmaskinens registre til de øverste flere operander af stakken i stedet for værtsmaskinens hukommelse

I en stakmaskine er de operander, der bruges i instruktionerne, altid ved en kendt forskydning (angivet i stakkemarkøren), fra et fast sted (bunden af ​​stakken, som i et hardwaredesign altid kan være på hukommelsesplacering nul), spare dyrebar cache eller in- CPU- lagring fra at blive brugt til at gemme ret mange hukommelsesadresser eller indeksnumre. Dette kan bevare sådanne registre og cache til brug i ikke-flow-beregning.

Midlertidige / lokale værdier

Nogle i branchen mener, at stakemaskiner udfører flere datacachecyklusser for midlertidige værdier og lokale variabler end registreringsmaskiner.

På stakemaskiner spildes midlertidige værdier ofte i hukommelsen, hvorimod på maskiner med mange registre disse vikarer normalt forbliver i registre. (Disse værdier skal dog ofte spildes i "aktiveringsrammer" ved afslutningen af ​​en procedurs definition, grundlæggende blok eller i det mindste i en hukommelsesbuffer under afbrydelsesbehandling). Værdier spildt til hukommelse tilføjer flere cachecyklusser. Denne spildeffekt afhænger af antallet af skjulte registre, der bruges til at buffer top-of-stack-værdier, af frekvensen af ​​indlejrede procedurekald og af værtscomputers afbrydelsesbehandlingshastigheder.

På registermaskiner, der anvender optimeringskompilatorer, er det meget almindeligt, at de mest brugte lokale variabler forbliver i registre frem for i stabelrammeceller. Dette eliminerer de fleste datacachecyklusser for at læse og skrive disse værdier. Udviklingen af ​​"stakplanlægning" til udførelse af live-variabel analyse og dermed bevarelse af nøglevariabler på stakken i længere perioder hjælper denne bekymring.

På den anden side skal registermaskiner spilde mange af deres registre til hukommelse på tværs af indlejrede procedurekald. Beslutningen om, hvilke registre der skal spildes, og hvornår, træffes statisk på kompileringstidspunktet snarere end på den dynamiske dybde af opkaldene. Dette kan føre til mere datacachetrafik end i en avanceret implementering af stakmaskiner.

Almindelige underudtryk

I registermaskiner kan en fælles subexpression (en subexpression, der bruges flere gange med den samme resultatværdi) kun evalueres én gang, og dens resultat gemmes i et hurtigt register. De efterfølgende genbrug har ingen tid eller kodeomkostninger, kun en registerreference. Denne optimering fremskynder enkle udtryk (f.eks. Indlæsning af variabel X eller markør P) samt mindre almindelige komplekse udtryk.

Med stackmaskiner kan resultater derimod gemmes på en af ​​to måder. For det første kan resultater gemmes ved hjælp af en midlertidig variabel i hukommelsen. Lagring og efterfølgende hentning koster yderligere instruktioner og yderligere datacachecyklusser. At gøre dette er kun en gevinst, hvis subexpressionsberegningen koster mere i tid end at hente fra hukommelsen, hvilket i de fleste stak CPU'er næsten altid er tilfældet. Det er aldrig umagen værd for simple variabler og markørhentninger, fordi de allerede har den samme pris for en datacachecyklus pr. Adgang. Det er kun marginalt værd for udtryk som f.eks X+1. Disse enklere udtryk udgør størstedelen af ​​redundante, optimerbare udtryk i programmer, der er skrevet på ikke-sammenhængende sprog. En optimerende compiler kan kun vinde på afskedigelser, som programmøren kunne have undgået i kildekoden.

Den anden måde efterlader en beregnet værdi på datastakken, og duplikerer den efter behov. Dette bruger operationer til at kopiere stabelposter. Stakken skal være dyb lav nok til CPU'ens tilgængelige kopiinstruktioner. Håndskrevet stakkode bruger ofte denne fremgangsmåde og opnår hastigheder som almindelige registreringsmaskiner. Desværre bruges algoritmer til optimal "stakplanlægning" ikke i vid udstrækning af programmeringssprog.

Rørledning

I moderne maskiner er tiden til at hente en variabel fra datacachen ofte flere gange længere end den tid, der er nødvendig for grundlæggende ALU -operationer. Et program kører hurtigere uden bås, hvis dets hukommelsesbelastninger kan startes flere cyklusser før den instruktion, der har brug for denne variabel. Komplekse maskiner kan gøre dette med en dyb pipeline og "ude af drift", der undersøger og kører mange instruktioner på én gang. Registreringsmaskiner kan endda gøre dette med meget enklere "i orden" hardware, en lav rørledning og lidt smartere kompilatorer. Indlæsningstrinnet bliver en separat instruktion, og denne instruktion er statisk planlagt meget tidligere i kodesekvensen. Compileren sætter uafhængige trin imellem.

Planlægning af hukommelsesadgang kræver eksplicitte, ekstra registre. Det er ikke muligt på stakemaskiner uden at udsætte et aspekt af mikroarkitekturen for programmøren. For udtrykket AB -skal B evalueres og skubbes umiddelbart før minus -trinnet. Uden stakpermutation eller hardware -multitrådning kan der sættes relativt lidt nyttig kode imellem, mens man venter på, at belastning B er færdig. Stabelmaskiner kan omgå hukommelsesforsinkelsen ved enten at have en dyb ud-af-ordre udførelsesrørledning, der dækker mange instruktioner på én gang, eller mere sandsynligt, at de kan permutere stakken, så de kan arbejde på andre arbejdsbyrder, mens belastningen fuldføres, eller de kan sammenflette udførelsen af ​​forskellige programtråde, som i Unisys A9 -systemet. Dagens stadigt mere parallelle beregningsbelastninger tyder på, at dette måske ikke er den ulempe, det tidligere er gjort.

Stackmaskiner kan udelade operandhentningstrinnet i en registermaskine. For eksempel i Java Optimized Processor (JOP) mikroprocessoren indtaster de to øverste operander i stakken direkte et datatransmissionskredsløb, der er hurtigere end registerfilen.

Udførelse uden for ordren

Den Tomasulo algoritme finder instruktion-niveau parallelisme ved at udstede instruktioner som bliver tilgængelig deres data. Konceptuelt er adresserne på positioner i en stak ikke anderledes end registerindekserne for en registerfil. Denne visning gør det muligt at anvende Tomasulo-algoritmen, der er ude af drift, med stabelmaskiner.

Out-of-order-udførelse i stakemaskiner ser ud til at reducere eller undgå mange teoretiske og praktiske vanskeligheder. Den citerede forskning viser, at en sådan stakmaskine kan udnytte parallelisme på instruktionsniveau, og den resulterende hardware skal cache data til instruktionerne. Sådanne maskiner omgår effektivt de fleste hukommelsesadgang til stakken. Resultatet opnår gennemløb (instruktioner pr. Ur ), der kan sammenlignes med RISC -registermaskiner, med meget højere kodetætheder (fordi operandadresser er implicitte).

Et problem, der blev rejst i forskningen, var, at det tager omkring 1.88 stakmaskininstruktioner at udføre arbejdet med en registermaskines RISC-instruktion. Konkurrencedygtige out-of-order-stakmaskiner kræver derfor omkring dobbelt så mange elektroniske ressourcer for at spore instruktioner ("udstationer stationer"). Dette kan kompenseres ved besparelser i instruktionscache og hukommelse og instruktionskodningskredsløb.

Skjuler en hurtigere registreringsmaskine indeni

Nogle enkle stabelmaskiner har et chipdesign, der er fuldt tilpasset helt ned til niveauet for individuelle registre. Toppen af ​​stack -adresseregisteret og N -toppen af ​​stack -databuffere er bygget af separate individuelle registerkredsløb med separate adders og ad hoc -forbindelser.

Imidlertid er de fleste stakmaskiner bygget af større kredsløbskomponenter, hvor N -databufferne lagres sammen i en registerfil og deler læse/skrive -busser. De afkodede stakkeinstruktioner kortlægges til en eller flere sekventielle handlinger på den skjulte registerfil. Belastninger og ALU ops virker på nogle få øverste registre, og implicitte spild og fyldninger virker på de nederste registre. Dekoderen tillader instruktionsstrømmen at være kompakt. Men hvis kodestrømmen i stedet havde eksplicitte registervalgte felter, som direkte manipulerede den underliggende registerfil, kunne kompilatoren udnytte alle registre bedre, og programmet ville køre hurtigere.

Mikroprogrammerede stakmaskiner er et eksempel på dette. Den indre mikrokodemotor er en slags RISC -lignende registermaskine eller en VLIW -lignende maskine, der bruger flere registerfiler. Når den styres direkte af opgavespecifik mikrokode, får den motor meget mere arbejde udført pr. Cyklus, end når den indirekte styres af tilsvarende stakkode til den samme opgave.

Objektkodeoversætterne til HP 3000 og Tandem T/16 er et andet eksempel. De oversatte stakkodesekvenser til ækvivalente sekvenser af RISC -kode. Mindre 'lokale' optimeringer fjernede meget af omkostningerne til en stakarkitektur. Reserveregistre blev brugt til at udregne gentagne adresseberegninger. Den oversatte kode bevarede stadig masser af emuleringsomkostninger på grund af uoverensstemmelsen mellem originale og målmaskiner. På trods af denne byrde matchede cykluseffektiviteten af ​​den oversatte kode cykluseffektiviteten af ​​den originale stakkode. Og da kildekoden blev genkompileret direkte til registermaskinen via optimering af kompilatorer, blev effektiviteten fordoblet. Dette viser, at stakarkitekturen og dens ikke-optimerende kompilatorer spildte over halvdelen af ​​strømmen fra den underliggende hardware.

Registerfiler er gode værktøjer til computing, fordi de har høj båndbredde og meget lav latens, sammenlignet med hukommelsesreferencer via datacaches. I en simpel maskine tillader registerfilen at læse to uafhængige registre og skrive en tredje, alt i en ALU-cyklus med en cyklus eller mindre latens. Hvorimod den tilsvarende datacache kun kan starte en læsning eller en skrivning (ikke begge) pr. Cyklus, og læsningen typisk har en latens på to ALU -cykler. Det er en tredjedel af gennemstrømningen ved to gange rørledningens forsinkelse. I en kompleks maskine som Athlon, der udfylder to eller flere instruktioner pr. Cyklus, tillader registerfilen at læse fire eller flere uafhængige registre og skrive to andre, alt i en ALU-cyklus med en cyklus latency. Mens den tilsvarende dobbeltportede datacache kun kan starte to læsninger eller skrivninger pr. Cyklus, med flere cyklusser af latenstid. Igen er det en tredjedel af registrenes gennemløb. Det er meget dyrt at bygge en cache med ekstra porte.

Da en stak er en komponent i de fleste softwareprogrammer, selv når den anvendte software ikke strengt taget er en stakmaskine, kan en hardware -stakemaskine måske mere efterligne den indre funktion af dens programmer. Processorregistre har en høj termisk pris, og en stakmaskine kan kræve højere energieffektivitet.

Afbryder

At reagere på en afbrydelse indebærer at gemme registre i en stak og derefter forgrening til afbrydelse af håndtererkode. Ofte reagerer stakmaskiner hurtigere på afbrydelser, fordi de fleste parametre allerede er på en stak, og der ikke er behov for at skubbe dem dertil. Nogle registermaskiner håndterer dette ved at have flere registerfiler, der øjeblikkeligt kan byttes, men det øger omkostningerne og bremser registerfilen.

Tolke

Tolke til virtuelle stakmaskiner er lettere at bygge end tolke til registermaskiner; logikken til håndtering af hukommelsesadressetilstande er kun ét sted i stedet for at blive gentaget i mange instruktioner. Stackmaskiner har også en tendens til at have færre variationer af en opcode; en generaliseret opcode håndterer både hyppige sager og uklare hjørnesager med hukommelsesreferencer eller opsætning af funktionsopkald. (Men kodetætheden forbedres ofte ved at tilføje korte og lange former til den samme operation.)

Tolke til virtuelle stakmaskiner er ofte langsommere end tolke til andre former for virtuel maskine. Denne afmatning er værst, når den kører på værtsmaskiner med dybe udførelsesrørledninger, f.eks. Nuværende x86 -chips.

I nogle tolke skal tolken udføre et N-vejs switch-spring for at afkode den næste opcode og forgrene sig til dens trin for den pågældende opcode. En anden metode til valg af opcodes er kode med gevind . Værtsmaskinens præhentningsmekanismer er ikke i stand til at forudsige og hente målet for det indekserede eller indirekte spring. Så værtsmaskinens udførelsespipeline skal genstarte hver gang den hostede tolk afkoder en anden virtuel instruktion. Dette sker oftere for virtuelle stakmaskiner end for andre stilarter af virtuel maskine.

Et eksempel er programmeringssproget Java . Dens kanoniske virtuelle maskine er angivet som en 8-bit stakmaskine. Imidlertid er den virtuelle Dalvik- maskine til Java, der bruges på Android- smartphones , en 16-bit virtuel registreringsmaskine-et valg truffet af effektivitetsmæssige årsager. Aritmetiske instruktioner henter eller gemmer lokale variabler direkte via 4-bit (eller større) instruktionsfelter. På samme måde erstattede version 5.0 af Lua sin virtuelle stakmaskine med en hurtigere virtuel registermaskine.

Siden den virtuelle Java -maskine blev populær, har mikroprocessorer anvendt avancerede brancheprediktorer til indirekte spring. Dette fremskridt undgår det meste af genstart af rørledninger fra N-vejsspring og eliminerer meget af de instruktionstællingsomkostninger, der påvirker stak tolke.

Se også

Referencer

eksterne links