QEMU.js: issa serju u bil-WASM

Darba darba ddeċidejt għall-gost jipprova r-riversibbiltà tal-proċess u titgħallem kif tiġġenera JavaScript (b'mod aktar preċiż, Asm.js) mill-kodiċi tal-magni. QEMU ntgħażlet għall-esperiment, u ftit tal-ħin wara nkiteb artiklu fuq Habr. Fil-kummenti ingħatajt il-parir li nagħmel il-proġett f'WebAssembly, u anke nieqaf lili nnifsi kważi lest B'xi mod ma ridtx il-proġett... Ix-xogħol kien għaddej, iżda bil-mod ħafna, u issa, reċentement f'dak l-artiklu deher kummentarju dwar is-suġġett "Allura kif spiċċa kollox?" Bi tweġiba għat-tweġiba dettaljata tiegħi, smajt “Dan qisu artiklu.” Ukoll, jekk tista ', se jkun hemm artiklu. Forsi xi ħadd isibha utli. Minnha l-qarrej jitgħallem xi fatti dwar id-disinn tal-backends tal-ġenerazzjoni tal-kodiċi QEMU, kif ukoll kif jikteb kompilatur Just-in-Time għal applikazzjoni tal-web.

kompiti

Peress li kont diġà tgħallimt kif "b'xi" nġib QEMU għal JavaScript, din id-darba ġie deċiż li nagħmilha bil-għaqal u ma tirrepetix żbalji qodma.

Żball numru wieħed: fergħa minn rilaxx tal-punt

L-ewwel żball tiegħi kien li fork il-verżjoni tiegħi mill-verżjoni upstream 2.4.1. Imbagħad deherli idea tajba: jekk teżisti rilaxx tal-punt, allura probabbilment huwa aktar stabbli minn 2.4 sempliċi, u aktar u aktar il-fergħa master. U peress li ppjanajt li nżid ammont ġust ta 'bugs tiegħi stess, ma kelli bżonn xejn ta' ħaddieħor. Probabbilment hekk irriżulta. Imma hawn il-ħaġa: QEMU ma joqgħodx, u f'xi punt saħansitra ħabbru l-ottimizzazzjoni tal-kodiċi ġġenerat b'10 fil-mija. "Iva, issa se niffriża," ħsibt u faqqgħet. Hawnhekk irridu nagħmlu digressjoni: minħabba n-natura b'ħajt wieħed ta 'QEMU.js u l-fatt li l-QEMU oriġinali ma jimplikax in-nuqqas ta' multi-threading (jiġifieri, il-kapaċità li simultanjament jopera diversi mogħdijiet ta 'kodiċi mhux relatati, u mhux biss "uża l-qlub kollha") hija kritika għaliha, il-funzjonijiet ewlenin tal-ħjut li kelli "jidawwarha" biex inkun kapaċi nsejjaħ minn barra. Dan ħoloq xi problemi naturali waqt l-għaqda. Madankollu, il-fatt li xi wħud mill-bidliet mill-fergħa master, li magħhom ippruvajt ngħaqqad il-kodiċi tiegħi, kienu wkoll ċirasa qabad fir-rilaxx tal-punt (u għalhekk fil-fergħa tiegħi) ukoll probabbilment ma kienx ikun miżjud konvenjenza.

B'mod ġenerali, iddeċidejt li xorta jagħmel sens li tarmi l-prototip, iżarmah għal partijiet u nibni verżjoni ġdida mill-bidu bbażata fuq xi ħaġa aktar friska u issa minn master.

Żball numru tnejn: metodoloġija TLP

Essenzjalment, dan mhuwiex żball, b'mod ġenerali, huwa biss karatteristika tal-ħolqien ta 'proġett f'kundizzjonijiet ta' nuqqas ta 'fehim sħiħ kemm ta' "fejn u kif nimxu?" u b'mod ġenerali "se naslu hemm?" F'dawn il-kundizzjonijiet programmazzjoni goffa kienet għażla ġustifikata, iżda, naturalment, ma ridtx nirrepetiha bla bżonn. Din id-darba ridt nagħmilha bil-għaqal: kommessi atomiċi, bidliet konxji fil-kodiċi (u mhux "jgħaqqad karattri każwali flimkien sakemm jikkompila (bi twissijiet)", kif darba qal Linus Torvalds dwar xi ħadd, skont Wikiquote), eċċ.

Żball numru tlieta: tidħol fl-ilma mingħajr ma tkun taf il-ford

Għadni ma neħlesx għal kollox minn dan, imma issa ddeċidejt li ma ssegwix it-triq tal-inqas reżistenza, u li nagħmilha "bħala adult", jiġifieri, nikteb il-backend tat-TCG tiegħi mill-bidu nett, sabiex ma nagħmelx. ikolli ngħid aktar tard, "Iva, dan naturalment, bil-mod, imma ma nistax nikkontrolla kollox - hekk inkiteb TCI..." Barra minn hekk, dan inizjalment deher bħala soluzzjoni ovvja, peress li Niġġenera kodiċi binarju. Kif jgħidu, “Ghent miġburaу, iżda mhux dak wieħed”: il-kodiċi huwa, ovvjament, binarju, iżda l-kontroll ma jistax jiġi sempliċement trasferit għalih - għandu jiġi mbuttat b'mod espliċitu fil-browser għall-kumpilazzjoni, li jirriżulta f'ċertu oġġett mid-dinja JS, li għad jeħtieġ li jiġu salvati x'imkien. Madankollu, fuq arkitetturi RISC normali, sa fejn nifhem, sitwazzjoni tipika hija l-ħtieġa li espliċitament reset il-cache tal-istruzzjoni għall-kodiċi riġenerat - jekk dan mhux dak li għandna bżonn, allura, fi kwalunkwe każ, huwa qrib. Barra minn hekk, mill-aħħar tentattiv tiegħi, tgħallimt li l-kontroll ma jidhirx li jiġi trasferit għan-nofs tal-blokka tat-traduzzjoni, għalhekk m'għandniex bżonn verament bytecode interpretat minn kwalunkwe offset, u nistgħu sempliċement niġġenerawha mill-funzjoni fuq it-TB .

Ġew u taw sieq

Għalkemm bdejt nikteb mill-ġdid il-kodiċi lura f'Lulju, daqqa ta' ħarta maġika ħarġet bla ma nnutat: normalment l-ittri minn GitHub jaslu bħala notifiki dwar tweġibiet għal Issues and Pull requests, iżda hawn, f'daqqa waħda semmi fil-ħajt Binaryen bħala backend qemu fil-kuntest, "Għamel xi ħaġa bħal dik, forsi jgħid xi ħaġa." Konna qed nitkellmu dwar l-użu tal-librerija relatata ta' Emscripten Binaryen biex toħloq WASM JIT. Ukoll, għidt li għandek liċenzja Apache 2.0 hemmhekk, u QEMU kollu kemm hu huwa mqassam taħt GPLv2, u mhumiex kompatibbli ħafna. F'daqqa waħda rriżulta li liċenzja tista 'tkun issewwiha b'xi mod (Ma nafx: forsi tibdilha, forsi liċenzjar doppju, forsi xi ħaġa oħra...). Dan, ovvjament, għamilni kuntent, għax sa dak iż-żmien kont diġà ħarist mill-qrib format binarju WebAssembly, u b'xi mod kont imdejjaq u inkomprensibbli. Kien hemm ukoll librerija li devour il-blokki bażiċi bil-graff tat-tranżizzjoni, tipproduċi l-bytecode, u anke tmexxiha fl-interpretu innifsu, jekk meħtieġ.

Imbagħad kien hemm aktar ittra fuq il-lista tal-posta QEMU, iżda din hija aktar dwar il-mistoqsija, "Min għandu bżonnha xorta waħda?" U huwa f'daqqa waħda, irriżulta li kien meħtieġ. Bħala minimu, tista 'tqaxxar flimkien il-possibbiltajiet ta' użu li ġejjin, jekk taħdem aktar jew inqas malajr:

  • tniedi xi ħaġa edukattiva mingħajr ebda installazzjoni
  • virtwalizzazzjoni fuq iOS, fejn, skond xnigħat, l-unika applikazzjoni li għandha d-dritt għall-ġenerazzjoni tal-kodiċi fuq il-fly hija magna JS (dan huwa minnu?)
  • dimostrazzjoni ta 'mini-OS - single-floppy, built-in, kull tip ta' firmware, eċċ...

Karatteristiċi tal-Browser Runtime

Kif diġà għedt, QEMU huwa marbut ma 'multithreading, iżda l-browser m'għandux. Ukoll, jiġifieri, le... Għall-ewwel ma kienet teżisti xejn, imbagħad dehru WebWorkers - sa fejn nifhem jien, dan huwa multithreading ibbażat fuq il-passaġġ tal-messaġġ mingħajr varjabbli kondiviżi. Naturalment, dan joħloq problemi sinifikanti meta jiġi portat kodiċi eżistenti bbażat fuq il-mudell tal-memorja kondiviża. Imbagħad, taħt pressjoni pubblika, ġie implimentat taħt l-isem SharedArrayBuffers. Ġie introdott gradwalment, iċċelebraw it-tnedija tiegħu f'browsers differenti, imbagħad iċċelebraw is-Sena l-Ġdida, u mbagħad Meltdown... Wara li waslu għall-konklużjoni li oħxon jew oħxon il-kejl tal-ħin, iżda bl-għajnuna ta 'memorja kondiviża u a ħajt inkrementa l-counter, huwa l-istess se taħdem b'mod pjuttost preċiż. Għalhekk iddiżattivajna l-multithreading b'memorja kondiviża. Jidher li aktar tard reġgħu daru, iżda, kif deher ċar mill-ewwel esperiment, hemm ħajja mingħajrha, u jekk iva, nippruvaw nagħmluha mingħajr ma noqogħdu fuq multithreading.

It-tieni karatteristika hija l-impossibbiltà ta 'manipulazzjonijiet ta' livell baxx mal-munzell: ma tistax sempliċement tieħu, issalva l-kuntest attwali u taqleb għal waħda ġdida b'munzell ġdid. Il-munzell tas-sejħiet huwa ġestit mill-magna virtwali JS. Jidher, x'inhi l-problema, peress li għadna ddeċidejna li namministraw il-flussi ta 'qabel kompletament manwalment? Il-fatt hu li l-blokk I/O f'QEMU huwa implimentat permezz ta 'coroutines, u dan huwa fejn manipulazzjonijiet ta' stack ta 'livell baxx ikunu utli. Fortunatament, Emscipten diġà fih mekkaniżmu għal operazzjonijiet asinkroniċi, anke tnejn: Asyncify и Interpretu. L-ewwel wieħed jaħdem permezz ta 'nefħa sinifikanti fil-kodiċi JavaScript iġġenerat u m'għadux appoġġjat. It-tieni huwa l-"mod korrett" attwali u jaħdem permezz tal-ġenerazzjoni tal-bytecode għall-interpretu nattiv. Taħdem, ovvjament, bil-mod, iżda ma nefħx il-kodiċi. Veru, l-appoġġ għal coroutines għal dan il-mekkaniżmu kellu jiġi kkontribwit b'mod indipendenti (diġà kien hemm coroutines miktuba għal Asyncify u kien hemm implimentazzjoni ta' bejn wieħed u ieħor l-istess API għal Emterpreter, għandek bżonn biss tikkonnettjahom).

Bħalissa, għadni ma rnexxilux naqsam il-kodiċi f'wieħed miġbur f'WASM u interpretat bl-użu ta 'Emterpreter, għalhekk l-apparati tal-blokk għadhom ma jaħdmux (ara fis-serje li jmiss, kif jgħidu...). Jiġifieri, fl-aħħar għandek tikseb xi ħaġa bħal din il-ħaġa umoristiċi f'saffi:

  • Blokk interpretat I/O. Ukoll, kont verament tistenna NVMe emulat b'rendiment nattiv? 🙂
  • kodiċi QEMU prinċipali kkumpilat b'mod statiku (traduttur, apparat ieħor emulat, eċċ.)
  • kodiċi tal-mistieden ikkumpilat b'mod dinamiku f'WASM

Karatteristiċi tas-sorsi QEMU

Kif probabilment diġà qtajt, il-kodiċi għall-emulazzjoni tal-arkitetturi mistiedna u l-kodiċi għall-ġenerazzjoni tal-istruzzjonijiet tal-magna ospitanti huma separati f'QEMU. Fil-fatt, huwa saħansitra ftit aktar diffiċli:

  • hemm arkitetturi mistiedna
  • hemm aċċeleraturi, jiġifieri, KVM għall-virtwalizzazzjoni tal-ħardwer fuq Linux (għal sistemi mistiedna u ospitanti kompatibbli ma 'xulxin), TCG għall-ġenerazzjoni tal-kodiċi JIT kullimkien. Nibda b'QEMU 2.9, deher appoġġ għall-istandard tal-virtwalizzazzjoni tal-ħardwer HAXM fuq Windows (id-dettalji)
  • jekk jintuża TCG u mhux virtwalizzazzjoni tal-ħardwer, allura għandu appoġġ separat għall-ġenerazzjoni tal-kodiċi għal kull arkitettura ospitanti, kif ukoll għall-interpretu universali
  • ... u madwar dan kollu - periferali emulati, user interface, migrazzjoni, record-replay, eċċ.

Mill-mod, kont taf: QEMU jista' jimita mhux biss il-kompjuter kollu, iżda wkoll il-proċessur għal proċess separat tal-utent fil-qalba ospitanti, li jintuża, pereżempju, mill-fuzzer AFL għal strumentazzjoni binarja. Forsi xi ħadd jixtieq itrasferixxi dan il-mod ta' tħaddim ta' QEMU għal JS? 😉

Bħall-biċċa l-kbira tas-softwer b'xejn li ilu żmien twil, QEMU huwa mibni permezz tas-sejħa configure и make. Ejja ngħidu li tiddeċiedi li żżid xi ħaġa: backend TCG, implimentazzjoni tal-ħajt, xi ħaġa oħra. M'għandekx tgħaġġla biex tkun ferħan/orrifikat (ssottolinja kif xieraq) bil-prospett li tikkomunika ma 'Autoconf - fil-fatt, configure QEMU huwa apparentement miktub minnu nnifsu u ma jiġi ġġenerat minn xejn.

Assemblaġġ tal-Web

Allura x'inhi din il-ħaġa msejħa WebAssembly (magħruf ukoll bħala WASM)? Dan huwa sostitut għal Asm.js, m'għadux jippretendi li huwa kodiċi JavaScript validu. Għall-kuntrarju, huwa purament binarju u ottimizzat, u anki sempliċement il-kitba ta 'numru sħiħ fih mhix sempliċi ħafna: għall-kumpattezza, hija maħżuna fil-format LEB128.

Jista' jkun li smajt dwar l-algoritmu ta' relooping għal Asm.js - dan huwa r-restawr ta' struzzjonijiet ta' kontroll tal-fluss ta' "livell għoli" (jiġifieri, jekk imbagħad inkella, loops, eċċ.), li għalihom huma ddisinjati magni JS, minn l-LLVM IR ta 'livell baxx, eqreb lejn il-kodiċi tal-magna esegwit mill-proċessur. Naturalment, ir-rappreżentazzjoni intermedja tal-QEMU hija eqreb tat-tieni. Jidher li hawn, bytecode, it-tmiem tat-torment... U mbagħad hemm blokki, if-then-else u loops!..

U din hija raġuni oħra għaliex Binaryen huwa utli: jista 'jaċċetta b'mod naturali blokki ta' livell għoli qrib dak li jkun maħżun fil-WASM. Iżda tista 'wkoll tipproduċi kodiċi minn graff ta' blokki bażiċi u tranżizzjonijiet bejniethom. Ukoll, diġà għedt li jaħbi l-format tal-ħażna tal-WebAssembly wara l-API C/C++ konvenjenti.

TCG (Ġeneratur tal-Kodiċi Ċkejkna)

GCT kien oriġinarjament backend għall-kompilatur C. Imbagħad, apparentement, ma setax jiflaħ il-kompetizzjoni mal-GCC, iżda fl-aħħar sab postu f'QEMU bħala mekkaniżmu ta 'ġenerazzjoni ta' kodiċi għall-pjattaforma ospitanti. Hemm ukoll backend TCG li jiġġenera xi bytecode astratt, li jiġi esegwit immedjatament mill-interpretu, iżda ddeċidejt li nevita li nużaha din id-darba. Madankollu, il-fatt li fil-QEMU diġà huwa possibbli li titħalla t-tranżizzjoni għat-TB iġġenerat permezz tal-funzjoni tcg_qemu_tb_exec, irriżulta li kien utli ħafna għalija.

Biex iżżid backend TCG ġdid mal-QEMU, trid toħloq subdirettorju tcg/<имя архитектуры> (f'dan il-każ, tcg/binaryen), u fih żewġ fajls: tcg-target.h и tcg-target.inc.c и jippreskrivi hija kollha dwar configure. Tista' tpoġġi fajls oħra hemmhekk, iżda, kif tista' taħsbu mill-ismijiet ta' dawn it-tnejn, it-tnejn se jkunu inklużi x'imkien: wieħed bħala fajl header regolari (huwa inkluż f' tcg/tcg.h, u dak wieħed diġà jinsab f'fajls oħra fid-direttorji tcg, accel u mhux biss), l-oħra - biss bħala snippet kodiċi fi tcg/tcg.c, iżda għandu aċċess għall-funzjonijiet statiċi tiegħu.

Iddeċidejt li nqatta' wisq ħin fuq investigazzjonijiet dettaljati ta 'kif taħdem, sempliċement ikkupjajt l-"skeletri" ta' dawn iż-żewġ fajls minn implimentazzjoni backend oħra, u b'mod onest indika dan fl-intestatura tal-liċenzja.

fajl tcg-target.h fih prinċipalment settings fil-formola #define-s:

  • kemm reġistri u x'wisa' hemm fuq l-arkitettura fil-mira (għandna kemm irridu, kemm irridu - il-mistoqsija hija aktar dwar x'se jiġi ġġenerat f'kodiċi aktar effiċjenti mill-browser fuq l-arkitettura "mira kompletament" ...)
  • allinjament ta 'struzzjonijiet ospitanti: fuq x86, u anke f'TCI, l-istruzzjonijiet mhumiex allinjati għal kollox, imma jien se npoġġi fil-buffer tal-kodiċi mhux struzzjonijiet għal kollox, iżda indikaturi għal strutturi tal-librerija Binaryen, għalhekk ngħid: 4 bytes
  • liema istruzzjonijiet fakultattivi jista 'jiġġenera l-backend - aħna ninkludu dak kollu li nsibu f'Binaryen, ħalli l-aċċeleratur ikisser il-bqija f'oħrajn aktar sempliċi innifsu
  • X'inhu d-daqs approssimattiv tal-cache TLB mitlub mill-backend. Il-fatt hu li fil-QEMU kollox huwa serju: għalkemm hemm funzjonijiet helper li jwettqu tagħbija/maħżen b'kont meħud tal-MMU mistieden (fejn inkunu mingħajru issa?), huma jiffrankaw il-cache tat-traduzzjoni tagħhom fil-forma ta' struttura, il- l-ipproċessar tagħhom huwa konvenjenti li jinkorporaw direttament fi blokki tax-xandir. Il-mistoqsija hija, liema offset f'din l-istruttura huwa pproċessat bl-aktar mod effiċjenti minn sekwenza żgħira u veloċi ta 'kmandi?
  • hawnhekk tista' ttejjeb l-iskop ta' wieħed jew żewġ reġistri riżervati, tippermetti li ssejjaħ TB permezz ta' funzjoni u b'għażla tiddeskrivi koppja ta' żgħar inline-funzjonijiet simili flush_icache_range (iżda dan mhux il-każ tagħna)

fajl tcg-target.inc.c, ovvjament, huwa ġeneralment ħafna akbar fid-daqs u fih diversi funzjonijiet obbligatorji:

  • inizjalizzazzjoni, inklużi restrizzjonijiet fuq liema struzzjonijiet jistgħu joperaw fuq liema operandi. Sfaċċatament ikkupjat minni minn backend ieħor
  • funzjoni li tieħu struzzjoni waħda interna bytecode
  • Tista 'wkoll tpoġġi funzjonijiet awżiljarji hawn, u tista' wkoll tuża funzjonijiet statiċi minn tcg/tcg.c

Għalija nnifsi, għażilt l-istrateġija li ġejja: fl-ewwel kliem tal-blokk tat-traduzzjoni li jmiss, ktibt erba’ indikaturi: marka tal-bidu (ċertu valur fil-viċinanza 0xFFFFFFFF, li ddetermina l-istat attwali tat-TB), il-kuntest, il-modulu ġġenerat, u n-numru maġiku għad-debugging. Għall-ewwel il-marka tpoġġiet fiha 0xFFFFFFFF - nfejn n - numru żgħir pożittiv, u kull darba li ġie esegwit permezz tal-interpretu żdied b'1. Meta laħaq 0xFFFFFFFE, il-kumpilazzjoni saret, il-modulu ġie ssejvjat fit-tabella tal-funzjoni, importat f'"lanċjar" żgħir, li fih marret l-eżekuzzjoni tcg_qemu_tb_exec, u l-modulu tneħħa mill-memorja QEMU.

Biex nipparafrażi l-klassiċi, "Crutch, kemm huwa marbut f'dan il-ħoss għall-qalb tal-proger...". Madankollu, il-memorja kienet qed tnixxi xi mkien. Barra minn hekk, kienet memorja ġestita minn QEMU! Kelli kodiċi li, meta nikteb l-istruzzjoni li jmiss (tajjeb, jiġifieri, pointer), ħassar dak li r-rabta tiegħu kienet f'dan il-post qabel, iżda dan ma għenx. Fil-fatt, fl-aktar każ sempliċi, QEMU jalloka memorja fl-istartjar u jikteb il-kodiċi ġenerat hemmhekk. Meta l-buffer jispiċċa, il-kodiċi jintrema 'l barra u dak li jmiss jibda jinkiteb minfloku.

Wara li studja l-kodiċi, indunajt li l-trick bin-numru magic ippermettili li ma nfallix fuq il-qerda tal-borġ billi neħles xi ħaġa ħażina fuq buffer mhux inizjalizzat fl-ewwel pass. Imma min jerġa jikteb il-buffer biex jevita l-funzjoni tiegħi aktar tard? Kif jagħtu parir l-iżviluppaturi tal-Emscripten, meta ħadt xi problema, daħħalt il-kodiċi li jirriżulta lura lejn l-applikazzjoni nattiva, waqqaft Mozilla Record-Replay fuqha... B'mod ġenerali, fl-aħħar indunajt ħaġa sempliċi: għal kull blokka, a struct TranslationBlock bid-deskrizzjoni tiegħu. Aqta fejn... Dak id-dritt, eżatt qabel il-blokk dritt fil-buffer. Meta rrealizzajt dan, iddeċidejt li nieqaf nuża l-krozzi (għall-inqas xi wħud), u sempliċement warfa n-numru maġiku, u ttrasferixxi l-kliem li kien fadal lil struct TranslationBlock, toħloq lista konnessa waħedha li tista 'tiġi traversata malajr meta l-cache tat-traduzzjoni jiġi reset, u tillibera l-memorja.

Xi krozzi jibqgħu: pereżempju, indikaturi mmarkati fil-buffer tal-kodiċi - xi wħud minnhom huma sempliċiment BinaryenExpressionRef, jiġifieri, huma jħarsu lejn l-espressjonijiet li jeħtieġ li jitqiegħdu b'mod lineari fil-blokk bażiku ġġenerat, parti hija l-kundizzjoni għat-tranżizzjoni bejn BBs, parti hija fejn imorru. Ukoll, diġà hemm blokki ppreparati għal Relooper li jeħtieġ li jiġu konnessi skont il-kundizzjonijiet. Biex tiddistingwihom, tintuża s-suppożizzjoni li huma kollha allinjati b'mill-inqas erba 'bytes, sabiex tkun tista' tuża b'mod sikur l-inqas żewġ bits sinifikanti għat-tikketta, għandek bżonn biss li tiftakar li tneħħiha jekk meħtieġ. Mill-mod, tikketti bħal dawn huma diġà użati fil-QEMU biex jindikaw ir-raġuni għall-ħruġ mill-linja TCG.

Bl-użu Binaryen

Il-moduli f'WebAssembly fihom funzjonijiet, li kull wieħed minnhom fih korp, li huwa espressjoni. L-espressjonijiet huma operazzjonijiet unarji u binarji, blokki li jikkonsistu f'listi ta' espressjonijiet oħra, fluss ta' kontroll, eċċ. Kif diġà għedt, il-fluss tal-kontroll hawnhekk huwa organizzat preċiżament bħala fergħat ta 'livell għoli, loops, sejħiet ta' funzjoni, eċċ. L-argumenti għall-funzjonijiet ma jgħaddux fuq il-munzell, iżda b'mod espliċitu, bħal f'JS. Hemm ukoll varjabbli globali, imma jien ma użajthomx, għalhekk mhux se ngħidlek dwarhom.

Il-funzjonijiet għandhom ukoll varjabbli lokali, numerati minn żero, tat-tip: int32 / int64 / float / double. F'dan il-każ, l-ewwel n varjabbli lokali huma l-argumenti mgħoddija lill-funzjoni. Jekk jogħġbok innota li għalkemm kollox hawnhekk mhuwiex għal kollox ta 'livell baxx f'termini ta' fluss ta 'kontroll, interi xorta ma jġorrux l-attribut "iffirmat/mhux iffirmat": kif in-numru jaġixxi jiddependi fuq il-kodiċi tal-operazzjoni.

B'mod ġenerali, Binaryen jipprovdi C-API sempliċi: inti toħloq modulu, fih toħloq espressjonijiet - unary, binary, blokki minn espressjonijiet oħra, kontroll tal-fluss, eċċ. Imbagħad inti toħloq funzjoni b'espressjoni bħala l-korp tagħha. Jekk int, bħali, għandek graff ta 'tranżizzjoni ta' livell baxx, il-komponent relooper jgħinek. Sa fejn nifhem, huwa possibbli li tuża kontroll ta 'livell għoli tal-fluss ta' eżekuzzjoni fi blokk, sakemm ma jmurx lil hinn mill-konfini tal-blokk - jiġifieri, huwa possibbli li ssir mogħdija mgħaġġla interna / bil-mod fergħat tal-passaġġ ġewwa l-kodiċi tal-ipproċessar tal-cache TLB integrat, iżda mhux biex tinterferixxi mal-fluss ta 'kontroll "estern". Meta teħles relooper, il-blokki tiegħu jinħelsu, meta teħles modulu, l-espressjonijiet, il-funzjonijiet, eċċ allokati lilu jisparixxu arena.

Madankollu, jekk trid tinterpreta kodiċi on the fly mingħajr ħolqien u tħassir bla bżonn ta 'istanza ta' interpretu, jista 'jagħmel sens li tpoġġi din il-loġika f'fajl C++, u minn hemm timmaniġġja direttament l-API C++ kollha tal-librerija, billi tevita lest- magħmula tgeżwir.

Allura biex tiġġenera l-kodiċi li għandek bżonn

// настроить глобальные параметры (можно поменять потом)
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);

... jekk insejt xi ħaġa, skużani, dan huwa biss biex tirrappreżenta l-iskala, u d-dettalji jinsabu fid-dokumentazzjoni.

U issa jibda l-crack-fex-pex, xi ħaġa bħal din:

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);

Sabiex b'xi mod tgħaqqad id-dinjiet ta 'QEMU u JS u fl-istess ħin taċċessa l-funzjonijiet ikkumpilati malajr, inħolqot firxa (tabella ta' funzjonijiet għall-importazzjoni fil-lanċjar), u l-funzjonijiet iġġenerati tqiegħdu hemm. Biex tikkalkula malajr l-indiċi, inizjalment intuża l-indiċi tal-blokka tat-traduzzjoni tal-kelma żero, iżda mbagħad l-indiċi kkalkulat permezz ta’ din il-formula beda sempliċement jidħol fil-qasam f’ struct TranslationBlock.

Mill-mod, demo (bħalissa b'liċenzja mċajpra) jaħdem tajjeb biss fil-Firefox. Iżviluppaturi Chrome kienu b'xi mod mhux lest għall-fatt li xi ħadd ikun irid joħloq aktar minn elf każ ta' moduli WebAssembly, għalhekk sempliċement allokaw gigabyte ta' spazju ta' indirizz virtwali għal kull...

Dak kollu għalissa. Forsi jkun hemm artiklu ieħor jekk ikun interessat xi ħadd. Jiġifieri, jibqa 'mill-inqas biss jagħmlu l-apparati blokk jaħdmu. Jista' wkoll jagħmel sens li l-kumpilazzjoni tal-moduli tal-WebAssembly issir asinkronika, kif soltu fid-dinja JS, peress li għad hemm interpretu li jista' jagħmel dan kollu sakemm il-modulu nattiv ikun lest.

Finalment enigma: inti kkumpilajt binarju fuq arkitettura ta '32 bit, iżda l-kodiċi, permezz ta' operazzjonijiet ta 'memorja, titla' minn Binaryen, x'imkien fuq il-munzell, jew x'imkien ieħor fil-2 GB ta 'fuq tal-ispazju tal-indirizz ta' 32 bit. Il-problema hija li mill-perspettiva ta 'Binaryen dan qed jaċċessa indirizz riżultanti kbir wisq. Kif taqra dan?

Fil-mod ta 'admin

Ma spiċċajtx nittestja dan, iżda l-ewwel ħsieb tiegħi kien "X'jiġri jekk ninstalla Linux 32-bit?" Imbagħad il-parti ta 'fuq tal-ispazju tal-indirizz se tkun okkupata mill-qalba. L-unika mistoqsija hija kemm se tkun okkupata: 1 jew 2 Gb.

B'mod ta' programmatur (għażla għall-prattikanti)

Ejja daqqa bużżieqa fil-quċċata tal-ispazju tal-indirizz. Jien stess ma nifhimx għaliex taħdem - hemm diġà għandu jkun hemm munzell. Imma "aħna prattikanti: kollox jaħdem għalina, imma ħadd ma jaf għaliex..."

// 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));
}

... huwa veru li mhuwiex kompatibbli ma 'Valgrind, iżda, fortunatament, Valgrind innifsu jimbotta lil kulħadd b'mod effettiv ħafna 'l barra minn hemm :)

Forsi xi ħadd jagħti spjegazzjoni aħjar ta’ kif jaħdem dan il-kodiċi tiegħi...

Sors: www.habr.com

Żid kumment