QEMU.js: bayi pataki ati pẹlu WASM

Ni ẹẹkan Mo pinnu fun igbadun fi mule awọn ipadasẹhin ti awọn ilana ati kọ ẹkọ bii o ṣe le ṣe ina JavaScript (diẹ sii ni pipe, Asm.js) lati koodu ẹrọ. A yan QEMU fun idanwo naa, ati ni akoko diẹ lẹhinna a kọ nkan kan lori Habr. Ninu awọn asọye Mo gba mi niyanju lati tun ṣe iṣẹ akanṣe ni WebAssembly, ati paapaa fi ara mi silẹ fere pari Emi ko fẹ bakan naa… Iṣẹ naa nlọ lọwọ, ṣugbọn laiyara pupọ, ati ni bayi, laipẹ ninu nkan yẹn han asọye lori koko-ọrọ “Nitorina bawo ni gbogbo rẹ ṣe pari?” Ni idahun si idahun alaye mi, Mo gbọ “Eyi dun bi nkan kan.” O dara, ti o ba le, nkan yoo wa. Boya ẹnikan yoo rii pe o wulo. Lati ọdọ rẹ oluka naa yoo kọ ẹkọ diẹ ninu awọn ododo nipa apẹrẹ ti awọn ẹhin iran koodu QEMU, bakanna bi o ṣe le kọ akopo Just-in-Time fun ohun elo wẹẹbu kan.

Awọn iṣẹ-ṣiṣe

Niwọn bi Mo ti kọ tẹlẹ bi o ṣe le “bakan” ibudo QEMU si JavaScript, ni akoko yii o pinnu lati ṣe pẹlu ọgbọn ati pe ko tun awọn aṣiṣe atijọ ṣe.

Nọmba aṣiṣe: ẹka lati itusilẹ aaye

Aṣiṣe akọkọ mi ni lati fi ẹya mi silẹ lati ẹya oke 2.4.1. Lẹhinna o dabi imọran ti o dara fun mi: ti itusilẹ ojuami ba wa, lẹhinna o ṣee ṣe iduroṣinṣin diẹ sii ju 2.4 ti o rọrun, ati paapaa diẹ sii ẹka naa master. Ati pe niwọn igba ti Mo gbero lati ṣafikun iye deede ti awọn idun ti ara mi, Emi ko nilo ẹnikẹni miiran rara. O ṣee ṣe bi o ṣe wa niyẹn. Ṣugbọn eyi ni ohun naa: QEMU ko duro duro, ati ni aaye kan wọn paapaa kede iṣapeye ti koodu ti ipilẹṣẹ nipasẹ 10 ogorun. "Bẹẹni, bayi Emi yoo di didi," Mo ro pe o si ṣubu. Nibi ti a nilo lati ṣe kan digression: nitori awọn nikan-asapo iseda ti QEMU.js ati awọn ti o daju wipe awọn atilẹba QEMU ko laisọfa awọn isansa ti olona-threading (ti o ni, ni agbara lati ni nigbakannaa ṣiṣẹ orisirisi awọn ọna koodu ti ko ni ibatan, ati). kii ṣe “lo gbogbo awọn kernels”) jẹ pataki fun rẹ, awọn iṣẹ akọkọ ti awọn okun Mo ni lati “tan jade” lati ni anfani lati pe lati ita. Eyi ṣẹda diẹ ninu awọn iṣoro adayeba lakoko iṣọpọ. Sibẹsibẹ, awọn ti o daju wipe diẹ ninu awọn ayipada lati eka master, pẹlu eyiti Mo gbiyanju lati dapọ koodu mi, tun jẹ ṣẹẹri ti a mu ni itusilẹ ojuami (ati nitorina ni ẹka mi) tun ṣee ṣe kii yoo ti ṣafikun irọrun.

Ni gbogbogbo, Mo pinnu pe o tun jẹ oye lati jabọ apẹrẹ naa, ṣajọpọ rẹ fun awọn apakan ki o kọ ẹya tuntun lati ibere ti o da lori nkan ti o ṣẹṣẹ ati ni bayi lati master.

Nọmba aṣiṣe meji: ilana TLP

Ni pataki, eyi kii ṣe aṣiṣe, ni gbogbogbo, o jẹ ẹya kan ti ṣiṣẹda iṣẹ akanṣe kan ni awọn ipo ti aiyede pipe ti mejeeji “ibiti ati bii o ṣe le gbe?” ati ni gbogbogbo “Ṣe a yoo de ibẹ?” Ni awọn ipo clumsy siseto jẹ aṣayan idalare, ṣugbọn, nipa ti ara, Emi ko fẹ lati tun ṣe lainidi. Ni akoko yii Mo fẹ lati ṣe pẹlu ọgbọn: awọn iṣẹ atomiki, awọn iyipada koodu mimọ (ati kii ṣe “pipa awọn ohun kikọ laileto papọ titi yoo fi ṣajọ (pẹlu awọn ikilo)”, gẹgẹ bi Linus Torvalds sọ lẹẹkan nipa ẹnikan, ni ibamu si Wikiquote), ati bẹbẹ lọ.

Nọmba aṣiṣe mẹta: gbigbe sinu omi lai mọ ford

Emi ko tun ti yọ kuro patapata, ṣugbọn nisisiyi Mo ti pinnu lati ma tẹle ipa ọna ti o kere ju, ati lati ṣe “gẹgẹbi agbalagba,” eyun, kọ ẹhin TCG mi lati ibere, nitorinaa kii ṣe. lati ni lati sọ nigbamii, "Bẹẹni, eyi jẹ dajudaju, laiyara, ṣugbọn emi ko le ṣakoso ohun gbogbo - ti o ni bi TCI ti kọ..." Jubẹlọ, yi lakoko dabi bi ohun kedere ojutu, niwon Mo ṣe ipilẹṣẹ koodu alakomeji. Bi wọn ṣe sọ, “Ghent pejọу, ṣugbọn kii ṣe ọkan naa": koodu naa jẹ, dajudaju, alakomeji, ṣugbọn iṣakoso ko le gbe lọ sibẹ nirọrun - o gbọdọ wa ni titari ni gbangba sinu ẹrọ aṣawakiri fun akopọ, ti o jẹ abajade ohun kan lati aye JS, eyiti o tun nilo lati wa ni fipamọ ibikan. Bibẹẹkọ, lori awọn faaji RISC deede, niwọn bi MO ti loye, ipo aṣoju ni iwulo lati tunto kaṣe itọnisọna ni gbangba fun koodu isọdọtun - ti eyi kii ṣe ohun ti a nilo, lẹhinna, ni eyikeyi ọran, o sunmọ. Ni afikun, lati igbiyanju mi ​​kẹhin, Mo kọ ẹkọ pe iṣakoso ko dabi ẹni pe a gbe lọ si aarin bulọọki itumọ, nitorinaa a ko nilo itumọ bytecode gaan lati eyikeyi aiṣedeede, ati pe a le jiroro ni ipilẹṣẹ lati iṣẹ naa lori TB. .

Wọ́n wá tapa

Botilẹjẹpe Mo bẹrẹ atunkọ koodu naa pada ni Oṣu Keje, tapa idan kan yọ jade lai ṣe akiyesi: nigbagbogbo awọn lẹta lati GitHub de bi awọn iwifunni nipa awọn idahun si Awọn ọran ati Awọn ibeere Fa, ṣugbọn nibi, lojiji mẹnuba ninu okun Binaryen bi qemu backend Ni ayika ọrọ, "O ṣe iru nkan bẹẹ, boya yoo sọ nkankan." A n sọrọ nipa lilo ile-ikawe ti o jọmọ Emscripten Binaryen lati ṣẹda WASM JIT. O dara, Mo sọ pe o ni iwe-aṣẹ Apache 2.0 nibẹ, ati pe QEMU lapapọ ti pin labẹ GPLv2, ati pe wọn ko ni ibaramu pupọ. Lojiji o wa jade pe iwe-aṣẹ le jẹ se atunse bakan (Emi ko mọ: boya yi pada, boya iwe-aṣẹ meji, boya nkan miiran ...). Eyi, dajudaju, mu inu mi dun, nitori ni akoko yẹn Mo ti wo ni pẹkipẹki alakomeji kika WebAssembly, ati ki o Mo wà bakan ìbànújẹ ati incomprehensible. Ile-ikawe tun wa ti yoo jẹ awọn bulọọki ipilẹ jẹ pẹlu aworan iyipada, ṣe agbejade bytecode, ati paapaa ṣiṣẹ ni onitumọ funrararẹ, ti o ba jẹ dandan.

Lẹhinna diẹ sii wa lẹta lori atokọ ifiweranṣẹ QEMU, ṣugbọn eyi jẹ diẹ sii nipa ibeere naa, “Tani o nilo rẹ lọnakọna?” Ati pe o jẹ lojiji, o wa ni jade ti o je pataki. Ni o kere ju, o le ṣajọpọ awọn aye lilo wọnyi ti o ba ṣiṣẹ diẹ sii tabi kere si ni yarayara:

  • ifilọlẹ ohun eko lai fifi sori ẹrọ ni gbogbo
  • agbara ipa lori iOS, nibo, ni ibamu si awọn agbasọ ọrọ, ohun elo nikan ti o ni ẹtọ si iran koodu lori fifo jẹ ẹrọ JS kan (Ṣe otitọ ni eyi?)
  • ifihan ti mini-OS - ẹyọ-floppy, ti a ṣe sinu, gbogbo iru famuwia, bbl

Browser asiko isise Awọn ẹya ara ẹrọ

Gẹgẹbi Mo ti sọ tẹlẹ, QEMU ti so si multithreading, ṣugbọn ẹrọ aṣawakiri ko ni. O dara, iyẹn, rara… Ni akọkọ ko si rara, lẹhinna WebWorkers farahan - niwọn bi mo ti ye mi, eyi jẹ multithreading da lori gbigbe ifiranṣẹ lai pín oniyipada. Nipa ti, eyi ṣẹda awọn iṣoro pataki nigbati o ba n gbe koodu to wa tẹlẹ da lori awoṣe iranti ti o pin. Lẹhinna, labẹ titẹ gbangba, o tun ṣe imuse labẹ orukọ SharedArrayBuffers. O ti ṣe ifilọlẹ diẹdiẹ, wọn ṣe ayẹyẹ ifilọlẹ rẹ ni awọn aṣawakiri oriṣiriṣi, lẹhinna wọn ṣe ayẹyẹ Ọdun Tuntun, lẹhinna Meltdown… Lẹhin eyi wọn wa si ipari pe isokuso tabi isokuso iwọn akoko, ṣugbọn pẹlu iranlọwọ ti iranti pinpin ati a okùn incrementing awọn counter, o ni gbogbo awọn kanna o yoo ṣiṣẹ jade lẹwa parí. Nitorinaa a ṣe alaabo multithreading pẹlu iranti pinpin. O dabi pe wọn ti tan-an pada nigbamii, ṣugbọn, bi o ti han gbangba lati inu idanwo akọkọ, igbesi aye wa laisi rẹ, ati pe ti o ba jẹ bẹ, a yoo gbiyanju lati ṣe laisi gbigbekele multithreading.

Ẹya keji jẹ ailagbara ti awọn ifọwọyi ipele-kekere pẹlu akopọ: o ko le mu nirọrun, ṣafipamọ ipo lọwọlọwọ ki o yipada si tuntun pẹlu akopọ tuntun. Akopọ ipe jẹ iṣakoso nipasẹ ẹrọ foju JS. O dabi pe, kini iṣoro naa, niwon a tun pinnu lati ṣakoso awọn ṣiṣan iṣaaju patapata pẹlu ọwọ? Otitọ ni pe bulọki I/O ni QEMU ni imuse nipasẹ awọn coroutines, ati pe eyi ni ibiti awọn ifọwọyi akopọ ipele kekere yoo wa ni ọwọ. Ni akoko, Emscipten ti ni ẹrọ kan fun awọn iṣẹ asynchronous, paapaa meji: Asyncify и Olutumọ. Ohun akọkọ n ṣiṣẹ nipasẹ bloat pataki ninu koodu JavaScript ti ipilẹṣẹ ati pe ko ṣe atilẹyin mọ. Awọn keji ni awọn ti isiyi "ona ọna" ati ki o ṣiṣẹ nipasẹ awọn bytecode iran fun abinibi onitumọ. O ṣiṣẹ, dajudaju, laiyara, ṣugbọn kii ṣe bloat koodu naa. Lootọ, atilẹyin fun awọn coroutines fun ẹrọ yii ni lati ṣe alabapin ni ominira (awọn coroutines ti wa tẹlẹ ti a kọ fun Asyncify ati imuse ti isunmọ API kanna fun Emterpreter, o kan nilo lati sopọ wọn).

Ni akoko yii, Emi ko ti ṣakoso lati pin koodu naa si ọkan ti a ṣajọ ni WASM ati itumọ nipa lilo Emterpreter, nitorinaa awọn ẹrọ idena ko ṣiṣẹ sibẹsibẹ (wo ninu jara atẹle, bi wọn ti sọ…). Iyẹn ni, ni ipari o yẹ ki o gba nkan bii nkan aladun aladun yii:

  • itumọ Àkọsílẹ I / O. O dara, ṣe o nireti gaan apẹẹrẹ NVMe pẹlu iṣẹ abinibi? 🙂
  • koodu QEMU akọkọ ti kojọpọ ni iṣiro (olutumọ, awọn ẹrọ miiran ti a ṣe apẹẹrẹ, ati bẹbẹ lọ)
  • dynamically compiled koodu alejo sinu WASM

Awọn ẹya ara ẹrọ ti awọn orisun QEMU

Bi o ti ṣee ṣe kiye si tẹlẹ, koodu fun apẹẹrẹ awọn ile ayaworan alejo ati koodu fun ṣiṣẹda awọn ilana ẹrọ agbalejo ti yapa ni QEMU. Ni otitọ, o jẹ ẹtan diẹ paapaa:

  • nibẹ ni o wa alejo architectures
  • ni accelerators, eyun, KVM fun ohun elo agbara lori Lainos (fun alejo ati awọn eto ogun ti o ni ibamu pẹlu ara wọn), TCG fun iran koodu JIT nibikibi. Bibẹrẹ pẹlu QEMU 2.9, atilẹyin fun boṣewa imudara ohun elo HAXM lori Windows han (awọn alaye)
  • Ti o ba ti lo TCG kii ṣe ohun elo ohun elo, lẹhinna o ni atilẹyin iran koodu lọtọ fun faaji agbalejo kọọkan, ati fun onitumọ gbogbo agbaye.
  • ati ni ayika gbogbo eyi - awọn agbeegbe apẹẹrẹ, wiwo olumulo, ijira, igbasilẹ-tun ṣe, ati bẹbẹ lọ.

Nipa ọna, ṣe o mọ: QEMU le ṣe apẹẹrẹ kii ṣe gbogbo kọnputa nikan, ṣugbọn tun ero isise fun ilana olumulo lọtọ ni ekuro agbalejo, eyiti o lo, fun apẹẹrẹ, nipasẹ fuzzer AFL fun ohun elo alakomeji. Boya ẹnikan yoo fẹ lati gbe ipo iṣẹ QEMU yii si JS? 😉

Bii sọfitiwia ọfẹ ti o duro pẹ pipẹ, QEMU ti kọ nipasẹ ipe naa configure и make. Jẹ ká sọ pé o pinnu lati fi nkankan: a TCG backend, o tẹle imuse, nkan miran. Maṣe yara lati ni idunnu / jaya (lalẹ bi o ṣe yẹ) ni ireti ti ibaraẹnisọrọ pẹlu Autoconf - ni otitọ, configure QEMU ká ti wa ni nkqwe ara-kọ ati ki o ti wa ni ko ti ipilẹṣẹ lati ohunkohun.

Apejọ Ayelujara

Nitorinaa kini nkan yii ti a pe ni WebAssembly (aka WASM)? Eyi jẹ rirọpo fun Asm.js, ko ṣe dibọn bi koodu JavaScript ti o wulo. Ni ilodi si, o jẹ alakomeji odasaka ati iṣapeye, ati paapaa kikọ odidi kan sinu rẹ kii ṣe rọrun pupọ: fun iwapọ, o ti fipamọ ni ọna kika. LEB128.

O le ti gbọ nipa algorithm relooping fun Asm.js - eyi ni atunṣe ti awọn ilana iṣakoso sisan "ipele giga" (ti o jẹ, ti o ba jẹ bẹ, awọn losiwajulosehin, bbl), fun eyiti awọn ẹrọ JS ṣe apẹrẹ, lati LLVM IR ipele kekere, ti o sunmọ koodu ẹrọ ti a ṣe nipasẹ ero isise naa. Nipa ti, aṣoju agbedemeji ti QEMU sunmọ keji. Yoo dabi pe nibi o wa, bytecode, opin ijiya ... Ati lẹhinna awọn ohun amorindun wa, ti o ba jẹ bẹ-miiran ati awọn losiwajulosehin!

Ati pe eyi jẹ idi miiran ti Binaryen ṣe wulo: o le nipa ti ara gba awọn bulọọki ipele giga ti o sunmọ ohun ti yoo wa ni ipamọ ni WASM. Ṣugbọn o tun le gbe koodu jade lati aworan kan ti awọn bulọọki ipilẹ ati awọn iyipada laarin wọn. O dara, Mo ti sọ tẹlẹ pe o tọju ọna kika ibi ipamọ WebAssembly lẹhin irọrun C / C ++ API.

TCG (Apilẹṣẹ koodu Kekere)

GTC je akọkọ backend fun olupilẹṣẹ C. Lẹhinna, o han gbangba, ko le koju idije pẹlu GCC, ṣugbọn ni ipari o rii aaye rẹ ni QEMU gẹgẹbi ilana iran koodu fun pẹpẹ agbalejo. Atilẹyin TCG tun wa ti o ṣe agbejade diẹ ninu awọn bytecode áljẹbrà, eyiti onitumọ ṣe lẹsẹkẹsẹ, ṣugbọn Mo pinnu lati yago fun lilo ni akoko yii. Sibẹsibẹ, otitọ pe ni QEMU o ṣee ṣe tẹlẹ lati jẹ ki iyipada si TB ti ipilẹṣẹ nipasẹ iṣẹ naa tcg_qemu_tb_exec, o wa ni jade lati wulo pupọ fun mi.

Lati ṣafikun ifẹhinti TCG tuntun si QEMU, o nilo lati ṣẹda iwe-itọnisọna kan tcg/<имя архитектуры> (Fun idi eyi, tcg/binaryen), ati pe o ni awọn faili meji: tcg-target.h и tcg-target.inc.c и paṣẹ o jẹ gbogbo nipa configure. O le fi awọn faili miiran sibẹ, ṣugbọn, bi o ṣe le gboju lati awọn orukọ ti awọn meji wọnyi, awọn mejeeji yoo wa ni ibikan: ọkan gẹgẹbi faili akọsori deede (o wa ninu rẹ). tcg/tcg.h, ati pe ọkan ti wa tẹlẹ ninu awọn faili miiran ninu awọn ilana tcg, accel ati ki o ko nikan), awọn miiran - nikan bi a koodu snippet ni tcg/tcg.c, sugbon o ni wiwọle si awọn oniwe-aimi awọn iṣẹ.

Ti pinnu pe Emi yoo lo akoko pupọ lori awọn iwadii alaye ti bii o ṣe n ṣiṣẹ, Mo kan daakọ “skeletons” ti awọn faili meji wọnyi lati imuse ẹhin miiran, ni otitọ tọka si eyi ni akọsori iwe-aṣẹ.

Ọna tcg-target.h ni o kun eto ninu awọn fọọmu #define-s:

  • melo ni awọn iforukọsilẹ ati iwọn wo ni o wa lori faaji ibi-afẹde (a ni ọpọlọpọ bi a ṣe fẹ, bi ọpọlọpọ bi a ṣe fẹ - ibeere naa jẹ diẹ sii nipa kini yoo ṣe ipilẹṣẹ sinu koodu daradara siwaju sii nipasẹ ẹrọ aṣawakiri lori “ibi-afẹde patapata” faaji ...)
  • titete awọn ilana ogun: lori x86, ati paapaa ni TCI, awọn ilana ko ni ibamu rara, ṣugbọn Emi yoo fi ifipamọ koodu kii ṣe ilana rara, ṣugbọn awọn itọkasi si awọn ẹya ile-ikawe Binaryen, nitorinaa Emi yoo sọ: 4 awọn baiti
  • Kini awọn ilana iyan ti ẹhin le ṣe ipilẹṣẹ - a pẹlu ohun gbogbo ti a rii ni Binaryen, jẹ ki ohun imuyara fọ iyokù si awọn ti o rọrun funrararẹ.
  • Kini iwọn isunmọ ti kaṣe TLB ti o beere nipasẹ ẹhin. Otitọ ni pe ni QEMU ohun gbogbo jẹ pataki: botilẹjẹpe awọn iṣẹ oluranlọwọ wa ti o ṣe fifuye / itaja ni akiyesi MMU alejo (nibo ni a yoo wa laisi rẹ bayi?), Wọn fipamọ kaṣe itumọ wọn ni irisi eto, awọn processing eyiti o rọrun lati fi sabe taara sinu awọn bulọọki igbohunsafefe. Ibeere naa ni kini aiṣedeede ninu eto yii ti ni ilọsiwaju daradara julọ nipasẹ ọna kekere ati iyara ti awọn aṣẹ?
  • Nibi o le tweak idi ti awọn iforukọsilẹ ọkan tabi meji ti o wa ni ipamọ, mu pipe TB ṣiṣẹ nipasẹ iṣẹ kan ati ni yiyan ṣe apejuwe tọkọtaya kekere kan inline-awọn iṣẹ bi flush_icache_range (ṣugbọn eyi kii ṣe ọran tiwa)

Ọna tcg-target.inc.c, dajudaju, maa n tobi pupọ ni iwọn ati pe o ni ọpọlọpọ awọn iṣẹ dandan:

  • ipilẹṣẹ, pẹlu awọn ihamọ lori eyiti awọn ilana le ṣiṣẹ lori eyiti awọn iṣẹ ṣiṣe. Laifọwọyi daakọ nipasẹ mi lati miiran backend
  • iṣẹ ti o gba ọkan ti abẹnu bytecode ilana
  • O tun le fi awọn iṣẹ iranlọwọ nibi, ati awọn ti o tun le lo aimi awọn iṣẹ lati tcg/tcg.c

Fun ara mi, Mo yan ilana atẹle yii: ninu awọn ọrọ akọkọ ti bulọọki itumọ atẹle, Mo kọ awọn itọka mẹrin: ami ibẹrẹ (iye kan ni agbegbe 0xFFFFFFFF, eyiti o pinnu ipo lọwọlọwọ ti TB), ọrọ-ọrọ, module ti ipilẹṣẹ, ati nọmba idan fun n ṣatunṣe aṣiṣe. Ni akọkọ ami ti a gbe sinu 0xFFFFFFFF - nnibo n - nọmba rere kekere kan, ati ni gbogbo igba ti o ti ṣiṣẹ nipasẹ onitumọ o pọ si nipasẹ 1. Nigbati o de 0xFFFFFFFE, akopo mu ibi, awọn module ti a ti fipamọ ni awọn tabili iṣẹ, wole sinu kekere kan "ififilọlẹ", sinu eyi ti ipaniyan lọ lati tcg_qemu_tb_exec, ati awọn module ti a kuro lati QEMU iranti.

Lati ṣe alaye awọn kilasika, "Crutch, Elo ni o ni idapọ ninu ohun yii fun okan proger ...". Sibẹsibẹ, iranti ti n jo ni ibikan. Pẹlupẹlu, o jẹ iṣakoso nipasẹ QEMU! Mo ni koodu kan ti, nigbati kikọ ẹkọ atẹle (daradara, iyẹn, itọka), paarẹ ẹni ti ọna asopọ rẹ wa ni aaye yii tẹlẹ, ṣugbọn eyi ko ṣe iranlọwọ. Lootọ, ninu ọran ti o rọrun julọ, QEMU pin iranti ni ibẹrẹ ati kọ koodu ti ipilẹṣẹ nibẹ. Nigbati ifipamọ ba pari, koodu naa yoo da jade ati pe atẹle bẹrẹ lati kọ ni aaye rẹ.

Lẹhin kika koodu naa, Mo rii pe ẹtan pẹlu nọmba idan gba mi laaye lati ma kuna lori iparun okiti nipa didasilẹ nkan ti ko tọ lori ifipamọ ti ko ni ibẹrẹ ni akọkọ kọja. Ṣugbọn tani tun kọwe ifipamọ lati fori iṣẹ mi nigbamii? Gẹgẹbi awọn olupilẹṣẹ Emscripten ṣe imọran, nigbati Mo sare sinu iṣoro kan, Mo gbe koodu abajade pada si ohun elo abinibi, ṣeto Mozilla Record-Replay lori rẹ… Ni gbogbogbo, ni ipari Mo rii nkan ti o rọrun: fun bulọọki kọọkan, a struct TranslationBlock pẹlu awọn oniwe-apejuwe. Gboju ibi ti... Iyẹn tọ, ni kete ṣaaju idinaduro ọtun ninu ifipamọ. Ni mimọ eyi, Mo pinnu lati dawọ lilo awọn crutches (o kere ju diẹ ninu awọn), ati nirọrun ju nọmba idan jade, ati gbe awọn ọrọ to ku si struct TranslationBlock, ṣiṣẹda atokọ ti o sopọ mọ ẹyọkan ti o le wa ni iyara nigbati kaṣe itumọ ti tunto, ati sọ iranti di ominira.

Diẹ ninu awọn crutches wa: fun apẹẹrẹ, awọn itọka ti o samisi ninu ifipamọ koodu - diẹ ninu wọn jẹ irọrun BinaryenExpressionRef, eyini ni, wọn wo awọn ọrọ ti o nilo lati fi sii laini si ipilẹ ipilẹ ti ipilẹṣẹ, apakan jẹ ipo fun iyipada laarin BBs, apakan ni ibiti o lọ. O dara, awọn bulọọki ti a ti pese tẹlẹ fun Relooper ti o nilo lati sopọ ni ibamu si awọn ipo. Lati ṣe iyatọ wọn, a lo arosinu pe gbogbo wọn ni ibamu nipasẹ o kere ju awọn baiti mẹrin, nitorinaa o le lo awọn die-die pataki meji ti o kere ju fun aami naa, o kan nilo lati ranti lati yọ kuro ti o ba jẹ dandan. Nipa ọna, iru awọn aami bẹ ti wa ni lilo tẹlẹ ni QEMU lati ṣe afihan idi ti ijade lupu TCG.

Lilo Binaryen

Awọn modulu ni WebAssembly ni awọn iṣẹ, ọkọọkan ninu eyiti o ni ara kan, eyiti o jẹ ikosile. Awọn ikosile jẹ awọn iṣẹ alakomeji ati alakomeji, awọn bulọọki ti o ni awọn atokọ ti awọn ikosile miiran, ṣiṣan iṣakoso, ati bẹbẹ lọ. Gẹgẹbi Mo ti sọ tẹlẹ, ṣiṣan iṣakoso nibi ti ṣeto ni deede bi awọn ẹka ipele giga, awọn losiwajulosehin, awọn ipe iṣẹ, ati bẹbẹ lọ. Awọn ariyanjiyan si awọn iṣẹ ko kọja lori akopọ, ṣugbọn ni gbangba, gẹgẹ bi ninu JS. Awọn oniyipada agbaye tun wa, ṣugbọn Emi ko lo wọn, nitorinaa Emi kii yoo sọ fun ọ nipa wọn.

Awọn iṣẹ tun ni awọn oniyipada agbegbe, nọmba lati odo, ti iru: int32 / int64 / float / ilọpo. Ni idi eyi, akọkọ n agbegbe awọn oniyipada ni awọn ariyanjiyan ti o kọja si iṣẹ naa. Jọwọ ṣe akiyesi pe botilẹjẹpe ohun gbogbo ti o wa nibi kii ṣe ipele kekere patapata ni awọn ofin ti ṣiṣan iṣakoso, awọn nọmba ko tun gbe abuda “fọwọsi / ti ko forukọsilẹ”: bii nọmba ṣe huwa da lori koodu iṣiṣẹ naa.

Ni gbogbogbo, Binaryen pese o rọrun C-API: o ṣẹda module, ninu re ṣẹda expressions - unary, alakomeji, ohun amorindun lati miiran expressions, Iṣakoso sisan, ati be be lo. Lẹhinna o ṣẹda iṣẹ kan pẹlu ikosile bi ara rẹ. Ti iwọ, bii emi, ni aworan iyipada ipele-kekere, paati relooper yoo ṣe iranlọwọ fun ọ. Niwọn bi mo ti loye, o ṣee ṣe lati lo iṣakoso ipele giga ti sisan ipaniyan ni bulọọki kan, niwọn igba ti ko kọja awọn aala ti bulọọki - iyẹn ni, o ṣee ṣe lati ṣe ọna iyara inu / lọra ipa ọna inu koodu sisẹ kaṣe TLB ti a ṣe sinu, ṣugbọn kii ṣe lati dabaru pẹlu ṣiṣan iṣakoso “ita”. Nigbati o ba ṣe igbasilẹ relooper kan, awọn bulọọki rẹ ni ominira; nigbati o ba gba module kan laaye, awọn ikosile, awọn iṣẹ, ati bẹbẹ lọ ti a pin si rẹ yoo parẹ. gbagede.

Bibẹẹkọ, ti o ba fẹ tumọ koodu lori fo laisi ẹda ti ko wulo ati piparẹ ti apẹẹrẹ onitumọ, o le jẹ oye lati fi ọgbọn yii sinu faili C ++ kan, ati lati ibẹ taara ṣakoso gbogbo C ++ API ti ile-ikawe naa, ni ikọja ṣetan- ṣe wrappers.

Nitorinaa lati ṣẹda koodu ti o nilo

// настроить глобальные параметры (можно поменять потом)
BinaryenSetAPITracing(0);

BinaryenSetOptimizeLevel(3);
BinaryenSetShrinkLevel(2);

// создать модуль
BinaryenModuleRef MODULE = BinaryenModuleCreate();

// описать типы функций (как создаваемых, так и вызываемых)
helper_type  BinaryenAddFunctionType(MODULE, "helper-func", BinaryenTypeInt32(), int32_helper_args, ARRAY_SIZE(int32_helper_args));
// (int23_helper_args приоб^Wсоздаются отдельно)

// сконструировать супер-мега выражение
// ... ну тут уж вы как-нибудь сами :)

// потом создать функцию
BinaryenAddFunction(MODULE, "tb_fun", tb_func_type, func_locals, FUNC_LOCALS_COUNT, expr);
BinaryenAddFunctionExport(MODULE, "tb_fun", "tb_fun");
...
BinaryenSetMemory(MODULE, (1 << 15) - 1, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
BinaryenAddMemoryImport(MODULE, NULL, "env", "memory", 0);
BinaryenAddTableImport(MODULE, NULL, "env", "tb_funcs");

// запросить валидацию и оптимизацию при желании
assert (BinaryenModuleValidate(MODULE));
BinaryenModuleOptimize(MODULE);

... ti MO ba gbagbe ohunkohun, binu, eyi jẹ lati ṣe aṣoju iwọn nikan, ati pe awọn alaye wa ninu iwe.

Ati ni bayi crack-fex-pex bẹrẹ, nkan bii eyi:

static char buf[1 << 20];
BinaryenModuleOptimize(MODULE);
BinaryenSetMemory(MODULE, 0, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
int sz = BinaryenModuleWrite(MODULE, buf, sizeof(buf));
BinaryenModuleDispose(MODULE);
EM_ASM({
  var module = new WebAssembly.Module(new Uint8Array(wasmMemory.buffer, $0, $1));
  var fptr = $2;
  var instance = new WebAssembly.Instance(module, {
      'env': {
          'memory': wasmMemory,
          // ...
      }
  );
  // и вот уже у вас есть instance!
}, buf, sz);

Lati le bakan sopọ awọn agbaye ti QEMU ati JS ati ni akoko kanna wọle si awọn iṣẹ ti a ṣajọpọ ni iyara, a ṣẹda akojọpọ kan (tabili awọn iṣẹ fun gbigbe wọle sinu ifilọlẹ), ati awọn iṣẹ ti ipilẹṣẹ ni a gbe sibẹ. Lati ṣe iṣiro itọka ni kiakia, atọka ti bulọọki itumọ ọrọ odo ni a lo lakoko bi o ti jẹ, ṣugbọn lẹhinna itọka ti a ṣe iṣiro nipa lilo agbekalẹ yii bẹrẹ lati wọ inu aaye ni irọrun. struct TranslationBlock.

Nipa ọna, demo (Lọwọlọwọ pẹlu iwe-aṣẹ alarinrin) nikan ṣiṣẹ daradara ni Firefox. Chrome Difelopa wà bakan ko setan si ni otitọ wipe ẹnikan yoo fẹ lati ṣẹda diẹ ẹ sii ju ẹgbẹrun a instances ti WebAssembly modulu, ki nwọn nìkan soto a gigabyte ti foju adirẹsi aaye fun kọọkan ...

Iyẹn ni gbogbo fun bayi. Boya nkan miiran yoo wa ti ẹnikan ba nifẹ si. Eyun, o wa ni o kere ju o kan ṣe Àkọsílẹ awọn ẹrọ ṣiṣẹ. O tun le jẹ oye lati jẹ ki akopọ ti awọn modulu WebAssembly jẹ asynchronous, gẹgẹ bi aṣa ni agbaye JS, nitori pe onitumọ tun wa ti o le ṣe gbogbo eyi titi di igba ti module abinibi ti ṣetan.

Níkẹyìn àlọ́ kan: o ti ṣajọ alakomeji lori faaji 32-bit, ṣugbọn koodu naa, nipasẹ awọn iṣẹ iranti, ngun lati Binaryen, ibikan lori akopọ, tabi ibomiiran ni oke 2 GB ti aaye adirẹsi 32-bit. Iṣoro naa ni pe lati oju wiwo Binaryen eyi n wọle si adirẹsi abajade ti o tobi ju. Bawo ni lati gba ni ayika yi?

Ni ọna admin

Emi ko pari idanwo yii, ṣugbọn ero akọkọ mi ni “Kini ti MO ba fi Linux 32-bit sori ẹrọ?” Lẹhinna apakan oke ti aaye adirẹsi naa yoo gba nipasẹ ekuro. Ibeere nikan ni iye ti yoo gba: 1 tabi 2 Gb.

Ni ọna pirogirama (aṣayan fun awọn oṣiṣẹ)

Jẹ ki a fẹ bubble ni oke aaye adirẹsi naa. Emi funrarami ko loye idi ti o fi ṣiṣẹ - nibẹ tẹlẹ akopọ gbọdọ wa. Ṣugbọn “a jẹ oṣiṣẹ adaṣe: ohun gbogbo ṣiṣẹ fun wa, ṣugbọn ko si ẹnikan ti o mọ idi…”

// 2gbubble.c
// Usage: LD_PRELOAD=2gbubble.so <program>

#include <sys/mman.h>
#include <assert.h>

void __attribute__((constructor)) constr(void)
{
  assert(MAP_FAILED != mmap(1u >> 31, (1u >> 31) - (1u >> 20), PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
}

O jẹ otitọ pe ko ni ibamu pẹlu Valgrind, ṣugbọn, da, Valgrind funrararẹ ni imunadoko gbogbo eniyan jade nibẹ :)

Boya ẹnikan yoo funni ni alaye ti o dara julọ ti bii koodu ti mi ṣe n ṣiṣẹ…

orisun: www.habr.com

Fi ọrọìwòye kun