QEMU.js: dáiríre anois agus le WASM

Uair amháin, chinn mé le haghaidh spraoi in-aisiompaitheacht an phróisis a chruthú agus foghlaim conas JavaScript (níos cruinne, Asm.js) a ghiniúint ó chód meaisín. Roghnaíodh QEMU don turgnamh, agus tamall ina dhiaidh sin scríobhadh alt ar Habr. Sna tuairimí cuireadh in iúl dom an tionscadal a athdhéanamh i WebAssembly, agus fiú mé féin a scor beagnach críochnaithe Ní raibh mé ag iarraidh an tionscadal ar bhealach éigin... Bhí an obair ag dul ar aghaidh, ach go han-mhall, agus anois, le déanaí san alt sin le feiceáil tráchtaireacht ar an ábhar "Mar sin, conas a tháinig sé chun críche?" Mar fhreagra ar mo fhreagra mionsonraithe, chuala mé “Is cosúil le halt é seo.” Bhuel, más féidir leat, beidh alt ann. B'fhéidir go mbeidh sé úsáideach do dhuine éigin. Foghlaimeoidh an léitheoir roinnt fíricí uaidh faoi dhearadh inneall giniúna cóid QEMU, chomh maith le conas tiomsaitheoir Just-in-Time a scríobh le haghaidh feidhmchlár gréasáin.

tascanna

Ós rud é go raibh foghlamtha agam cheana féin conas QEMU a "phortadh ar bhealach éigin" go JavaScript, socraíodh an uair seo é a dhéanamh go ciallmhar agus gan seanbhotúin a dhéanamh arís.

Earráid uimhir a haon: brainse ón bpointe scaoileadh

Ba é an chéad botún a bhí agam ná mo leagan a fhorc ón leagan in aghaidh an tsrutha 2.4.1. Ansin ba smaoineamh maith é domsa: má tá scaoileadh pointe ann, is dócha go bhfuil sé níos cobhsaí ná 2.4 simplí, agus níos mó fós ná an brainse. master. Agus ós rud é go raibh sé beartaithe agam cuid mhaith de mo fhabhtanna féin a chur leis, ní raibh aon duine eile ag teastáil uaim. Is dócha gur mar sin a tharla sé. Ach seo an rud: ní sheasann QEMU, agus ag pointe éigin d’fhógair siad fiú leas iomlán a bhaint as an gcód ginte faoi 10 faoin gcéad. Anseo ní mór dúinn céimlaghdú a dhéanamh: mar gheall ar nádúr aon-snáithithe QEMU.js agus ar an bhfíric nach dtugann an QEMU bunaidh le tuiscint nach bhfuil il-snáithe (is é sin, an cumas chun roinnt cosáin chóid neamhghaolmhara a oibriú ag an am céanna, agus ní hamháin “bain úsáid as gach eithne”) ríthábhachtach dó, is iad príomhfheidhmeanna na snáitheanna a bhí orm "é a chasadh" le bheith in ann glaoch ón taobh amuigh. Chruthaigh sé seo roinnt fadhbanna nádúrtha le linn an chumaisc. Mar sin féin, ar an bhfíric go bhfuil roinnt de na hathruithe as an brainse master, lena ndearna mé iarracht mo chód a chumasc, a roghnaíodh freisin silíní sa scaoileadh pointe (agus dá bhrí sin i mo bhrainse) is dócha nach mbeadh áisiúlacht breise acu freisin.

Go ginearálta, chinn mé go ndéanann sé ciall fós an fhréamhshamhail a chaitheamh amach, é a dhíchóimeáil le haghaidh páirteanna agus leagan nua a thógáil ón tús bunaithe ar rud éigin níos úire agus anois ó master.

Botún uimhir a dó: modheolaíocht TLP

Go bunúsach, ní botún é seo, go ginearálta, níl ann ach gné de thionscadal a chruthú i gcoinníollacha míthuisceana iomlán ar “cá háit agus conas bogadh?” agus go ginearálta “an dtiocfaimid ann?” Sna coinníollacha seo cláir clumsy rogha inchosanta a bhí ann, ach, ar ndóigh, ní raibh mé ag iarraidh é a dhéanamh arís gan ghá. An uair seo bhí mé ag iarraidh é a dhéanamh go ciallmhar: gealltanais adamhach, athruithe comhfhiosacha ar chóid (agus gan “carachtair randamacha a cheangal le chéile go dtí go dtiomsaíonn sé (le rabhaidh)”, mar a dúirt Linus Torvalds uair amháin faoi dhuine, de réir Vicíquote), etc.

Botún uimhir a trí: dul isteach san uisce i ngan fhios don áth

Ní bhfuair mé réidh leis seo go hiomlán go fóill, ach anois tá cinneadh déanta agam gan an cosán is lú frithsheasmhachta a leanúint ar chor ar bith, agus é a dhéanamh “mar dhuine fásta,” is é sin, mo inneall TCG a scríobh ón tús, ionas nach a rá níos déanaí, "Sea, tá sé seo ar ndóigh, go mall, ach ní féidir liom a rialú gach rud - sin mar a scríobhtar TCI ..." Ina theannta sin, ba chosúil gur réiteach soiléir é seo ar dtús, ós rud é Ginim cód dénártha. Mar a deir siad, “Bhailigh Ghentу, ach ní hé sin”: tá an cód, ar ndóigh, dénártha, ach ní féidir rialú a aistriú go simplí chuige - ní mór é a bhrú go sainráite isteach sa bhrabhsálaí lena thiomsú, rud a fhágann go bhfuil rud áirithe ón domhan JS, a bhfuil gá fós leis. a shábháil áit éigin. Mar sin féin, ar ghnáth-ailtireachtaí RISC, chomh fada agus a thuigim, is cás tipiciúil é an gá atá le taisce treoracha a athshocrú go sainráite le haghaidh cód athghinte - más rud é nach é seo a theastaíonn uainn, ansin, in aon chás, tá sé gar. Ina theannta sin, ón iarracht dheireanach a rinne mé, d'fhoghlaim mé nach cosúil go n-aistrítear rialú go lár an bhloc aistriúcháin, agus mar sin ní gá dúinn bytecode a léirmhíniú ó aon fhritháireamh, agus is féidir linn a ghiniúint go simplí ón bhfeidhm ar TB. .

Tháinig siad agus chiceáil

Cé gur thosaigh mé ag athscríobh an chóid ar ais i mí Iúil, tháinig cic draíochta suas gan aird: go hiondúil tagann litreacha ó GitHub mar fhógraí faoi fhreagraí ar iarratais Eisiúint agus Tarraingthe, ach anseo, go tobann lua sa snáithe Binaryen mar inneall qemu sa chomhthéacs, "Rinne sé rud éigin mar sin, b'fhéidir go ndéarfaidh sé rud éigin." Bhíomar ag caint faoi leabharlann a bhaineann le Emscripten a úsáid Dénárthaigh chun WASM JIT a chruthú. Bhuel, dúirt mé go bhfuil ceadúnas Apache 2.0 agat ann, agus déantar QEMU ina iomláine a dháileadh faoi GPLv2, agus níl siad an-luí. Go tobann d'éirigh sé amach gur féidir le ceadúnas a shocrú ar bhealach éigin (Níl a fhios agam: b’fhéidir é a athrú, b’fhéidir décheadúnú, b’fhéidir rud éigin eile...). Chuir sé seo áthas orm, ar ndóigh, mar faoin am sin bhí mé ag breathnú go géar cheana féin formáid dhénártha WebAssembly, agus bhí mé brónach agus dothuigthe ar bhealach éigin. Bhí leabharlann ann freisin a bhainfeadh na bloic bhunúsacha leis an ngraf trasdula, a dhéanfadh an bytecode, agus fiú é a rith san ateangaire féin, dá mba ghá.

Ansin bhí níos mó litir ar an liosta seoltaí QEMU, ach tá sé seo níos mó mar gheall ar an gceist, “Cé atá de dhíth ar aon nós?” Agus tá sé go tobann, d'éirigh sé amach go raibh sé riachtanach. Ar a laghad, is féidir leat féidearthachtaí úsáide den sórt sin a bhriseadh le chéile má oibríonn sé níos tapúla nó níos lú:

  • rud éigin oideachais a sheoladh gan aon suiteáil ar chor ar bith
  • virtualization ar iOS, áit, de réir ráflaí, an t-aon fheidhmchlár a bhfuil an ceart chun cód a ghiniúint ar an eitilt ná inneall JS (an bhfuil sé seo fíor?)
  • léiriú mion-OS - singil flapach, ionsuite, gach cineál firmware, etc.

Gnéithe Runtime Brabhsálaí

Mar a dúirt mé cheana, tá QEMU ceangailte le multithreading, ach níl sé ag an mbrabhsálaí. Bhuel, is é sin, ní hea... Ar dtús ní raibh sé ann ar chor ar bith, ansin bhí an chuma ar WebWorkers - chomh fada agus a thuigim, tá sé seo ilshnáithe bunaithe ar theachtaireacht a rith gan athróga roinnte. Ar ndóigh, cruthaíonn sé seo fadhbanna suntasacha nuair a bhíonn an cód atá ann cheana féin á aistriú bunaithe ar an tsamhail chuimhne roinnte. Ansin, faoi bhrú an phobail, cuireadh i bhfeidhm é faoin ainm freisin SharedArrayBuffers. Tugadh isteach de réir a chéile é, rinne siad ceiliúradh ar a seoladh i mbrabhsálaithe éagsúla, ansin cheiliúir siad an Bhliain Nua, agus ansin Meltdown... Ina dhiaidh sin tháinig siad ar an tuairim go raibh an tomhas ama garbh nó garbh, ach le cabhair ó chuimhne roinnte agus a snáithe incriminteach an gcuntar, tá sé ar fad mar an gcéanna oibreoidh sé amach go cruinn go leor. Mar sin dhíchumasíomar multithreading le cuimhne roinnte. Dealraíonn sé gur thiontaigh siad ar ais air níos déanaí, ach, mar ba léir ón gcéad turgnamh, tá saol gan é, agus más amhlaidh, déanfaimid iarracht é a dhéanamh gan a bheith ag brath ar il-snáithe.

Is é an dara gné nach féidir ionramhálacha ar leibhéal íseal a dhéanamh leis an gcruach: ní féidir leat an comhthéacs reatha a thógáil, a shábháil agus athrú go dtí ceann nua le stack nua. Is é meaisín fíorúil JS a bhainistíonn an chairn glaonna. Is cosúil, cad é an fhadhb, ós rud é gur shocraigh muid fós na sreafaí roimhe seo a bhainistiú go hiomlán de láimh? Is é fírinne an scéil go gcuirtear bloc I/O i QEMU i bhfeidhm trí choroutines, agus seo an áit a mbeadh ionramhálacha cruachta ar leibhéal íseal áisiúil. Ar ámharaí an tsaoil, tá meicníocht ag Emscipten cheana féin le haghaidh oibríochtaí asincrónacha, fiú dhá cheann: Asincigh и Impire. Oibríonn an chéad cheann trí bloat suntasach sa chód JavaScript a ghintear agus ní thacaítear leis a thuilleadh. Is é an dara ceann an "bealach ceart" reatha agus oibríonn sé trí ghiniúint bytecode don ateangaire dúchais. Oibríonn sé, ar ndóigh, go mall, ach ní bloat sé an cód. Fíor, b'éigean tacaíocht a thabhairt do coroutines don mheicníocht seo go neamhspleách (bhí coroutines scríofa cheana féin le haghaidh Asyncify agus bhí cur i bhfeidhm thart ar an API céanna le haghaidh Emterpreter, ní gá duit ach iad a nascadh).

I láthair na huaire, níor éirigh liom an cód a roinnt i gceann a tiomsaíodh i WASM agus a léirmhíniú ag baint úsáide as Emterpreter, mar sin ní oibríonn blocghléasanna fós (féach sa chéad sraith eile, mar a deir siad...). Is é sin, sa deireadh ba chóir duit rud éigin mar an rud sraitheach greannmhar seo a fháil:

  • bloc léirmhínithe I/O. Bhuel, an raibh tú ag súil le NVMe aithrise le feidhmíocht dhúchasach? 🙂
  • príomhchód QEMU tiomsaithe go statach (aistritheoir, gléasanna aithrise eile, etc.)
  • cód aoi tiomsaithe go dinimiciúil i WASM

Gnéithe foinsí QEMU

Mar is dócha go ndearna tú buille faoi thuairim cheana féin, tá an cód le haghaidh aithris a dhéanamh ar ailtireachtaí aoi agus an cód chun treoracha meaisín óstach a ghiniúint scartha i QEMU. Go deimhin, tá sé beagán níos deacra:

  • tá ailtireachtaí aoi
  • luasairí, eadhon, KVM le haghaidh fíorúlú crua-earraí ar Linux (do chórais aoi agus óstacha atá comhoiriúnach lena chéile), TCG le haghaidh giniúint cód JIT áit ar bith. Ag tosú le QEMU 2.9, bhí tacaíocht le haghaidh caighdeán fíorúlaithe crua-earraí HAXM ar Windows le feiceáil (na sonraí)
  • má úsáidtear TCG agus nach fíorúlú crua-earraí é, tá tacaíocht giniúna cód ar leith aige do gach ailtireacht óstach, chomh maith leis an ateangaire uilíoch
  • ... agus thart ar seo go léir - forimeallaigh aithrise, comhéadan úsáideora, imirce, taifead-athimirt, etc.

Dála an scéil, an raibh a fhios agat: Is féidir le QEMU aithris a dhéanamh ní hamháin ar an ríomhaire ar fad, ach freisin ar an bpróiseálaí le haghaidh próiseas úsáideora ar leithligh san eithne óstach, a úsáideann an doiléir AFL, mar shampla, le haghaidh ionstraimíochta dénártha. B'fhéidir gur mhaith le duine an modh oibríochta seo de QEMU a aistriú chuig JS? 😉

Cosúil leis an gcuid is mó de na bogearraí saor in aisce le fada an lá, tógtar QEMU tríd an nglao configure и make. Ligean le rá go gcinnfidh tú rud éigin a chur leis: inneall TCG, cur i bhfeidhm snáithe, rud éigin eile. Ná bíodh deifir ort le bheith sásta/faitíosach (fínigh mar is cuí) agus tú ag súil le cumarsáid a dhéanamh le Autoconf - go deimhin, configure Is cosúil go bhfuil QEMU féinscríofa agus ní ghintear é ó rud ar bith.

WebAssembly

Mar sin, cad a thugtar ar an rud seo WebAssembly (aka WASM)? Tá sé seo in áit Asm.js, nach bhfuil ag ligean air gur chód JavaScript bailí é a thuilleadh. Ar a mhalairt, tá sé dénártha agus optamaithe amháin, agus fiú go simplí a scríobh slánuimhir isteach é nach bhfuil an-simplí: le haghaidh compactness, tá sé stóráilte san fhormáid LEB128.

Seans gur chuala tú faoin algartam athlúbála do Asm.js - is é seo athchóiriú na dtreoracha rialaithe sreafa “ardleibhéil” (is é sin, más rud é-mar sin, lúba, etc.), a bhfuil innill JS deartha dóibh, ó an LLVM IR íseal-leibhéal, níos gaire don chód meaisín arna fhorghníomhú ag an bpróiseálaí. Ar ndóigh, tá ionadaíocht idirmheánach QEMU níos gaire don dara ceann. Dhealródh sé go bhfuil anseo, bytecode, deireadh an chrá ... Agus ansin tá bloic, más rud é-ansin-eile agus lúba!..

Agus is cúis eile é seo cén fáth go bhfuil Binaryen úsáideach: is féidir leis go nádúrtha glacadh le bloic ardleibhéil in aice leis an méid a stóráiltear i WASM. Ach is féidir leis cód a tháirgeadh freisin ó ghraf de bhunbhloic agus trasdulta eatarthu. Bhuel, tá sé ráite agam cheana féin go gcuireann sé an fhormáid stórála WebAssembly i bhfolach taobh thiar den API áisiúil C/C ++.

TCG (Gineadóir Cód Beag bídeach)

TCG bhí ar dtús Inneall don tiomsaitheoir C. Ansin, de réir dealraimh, níorbh fhéidir leis an iomaíocht le GCC a sheasamh, ach sa deireadh fuair sé a áit i QEMU mar mheicníocht giniúna cód don ardán óstach. Tá inneall TCG ann freisin a ghineann roinnt bytecode teibí, a fhorghníomhaíonn an t-ateangaire láithreach, ach chinn mé gan é a úsáid an uair seo. Mar sin féin, ar an bhfíric go bhfuil i QEMU is féidir cheana féin a chur ar chumas an t-aistriú chuig an TB ginte tríd an fheidhm tcg_qemu_tb_exec, d'éirigh sé amach a bheith an-úsáideach dom.

Chun inneall TCG nua a chur le QEMU, ní mór duit fochomhadlann a chruthú tcg/<имя архитектуры> (sa chás seo, tcg/binaryen), agus tá dhá chomhad ann: tcg-target.h и tcg-target.inc.c и forordú tá sé ar fad faoi configure. Is féidir leat comhaid eile a chur ann, ach, mar is féidir leat buille faoi thuairim ó ainmneacha an dá cheann seo, cuirfear an dá cheann acu san áireamh áit éigin: ceann amháin mar chomhad ceanntásca rialta (tá sé san áireamh i tcg/tcg.h, agus go bhfuil an ceann sin cheana féin i gcomhaid eile sna heolairí tcg, accel agus ní amháin), an ceann eile - ach amháin mar bhlúire cód i tcg/tcg.c, ach tá rochtain aige ar a fheidhmeanna statacha.

Agus cinneadh á dhéanamh agam go gcaithfinn an iomarca ama ar imscrúduithe mionsonraithe ar an gcaoi a n-oibríonn sé, níor chóipeáil mé ach “cnámharlaigh” an dá chomhad seo ó chur i bhfeidhm inneall eile, rud a léirigh go hionraic i gceanntásc an cheadúnais.

comhad tcg-target.h go príomha socruithe san fhoirm #define-í:

  • cé mhéad clár agus cén leithead atá ar an sprioc-ailtireacht (tá an oiread agus is mian linn, an oiread agus is mian linn - tá an cheist níos mó faoi cad a ghinfidh an brabhsálaí isteach i gcód níos éifeachtaí ar an ailtireacht "sprioc go hiomlán" ...)
  • ailíniú na dtreoracha óstach: ar x86, agus fiú i TCI, níl na treoracha ailínithe ar chor ar bith, ach táim chun maolán an chóid a chur isteach ní treoracha ar chor ar bith, ach leideanna maidir le struchtúir leabharlainne Binaryen, mar sin déarfaidh mé: 4 bearta
  • cad iad na treoracha roghnacha is féidir leis an inneall a ghiniúint - cuirimid san áireamh gach rud a aimsímid i Binaryen, lig don luasaire an chuid eile a bhriseadh ina cinn níos simplí é féin
  • Cad é thart ar mhéid an taisce TLB a d'iarr an t-innill. Is é fírinne an scéil go bhfuil gach rud dáiríre i QEMU: cé go bhfuil feidhmeanna cúntóra ann a fheidhmíonn ualach/stóráil ag cur san áireamh an t-aoi MMU (cá mbeimis gan é anois?), sábhálann siad a dtaisce aistriúcháin i bhfoirm struchtúir, an a bhfuil sé áisiúil a phróiseáil a leabú go díreach i mbloic chraolta. Is í an cheist, cén fhritháireamh sa struchtúr seo is éifeachtaí a phróiseáiltear le seicheamh beag agus tapa orduithe?
  • anseo is féidir leat cuspóir chlár forchoimeádta amháin nó dhó a tweak, cuir glaoch ar TB trí fheidhm agus cur síos a dhéanamh go roghnach ar chúpla clár inline-feidhmeanna cosúil le flush_icache_range (ach ní hé seo ár gcás)

comhad tcg-target.inc.c, ar ndóigh, tá sé i bhfad níos mó de ghnáth agus tá roinnt feidhmeanna éigeantacha ann:

  • tosaigh, lena n-áirítear srianta ar a bhféadfaidh treoracha oibriú ar a n-oibríonn. Arna chóipeáil go soiléir agam ó inneall eile
  • feidhm a ghlacann teagasc inmheánach bytecode amháin
  • Is féidir leat feidhmeanna cúnta a chur anseo freisin, agus is féidir leat feidhmeanna statacha a úsáid freisin ó tcg/tcg.c

Maidir liom féin, roghnaigh mé an straitéis seo a leanas: i gcéad fhocail an chéad bhloc aistriúcháin eile, scríobh mé síos ceithre phointe: marc tosaigh (luach áirithe sa chomharsanacht 0xFFFFFFFF, a chinn staid reatha an TB), comhthéacs, modúl ginte, agus uimhir draíochta le haghaidh dífhabhtaithe. Ar dtús cuireadh an marc isteach 0xFFFFFFFF - nI gcás ina n - líon beag deimhneach, agus gach uair a rinneadh é tríd an ateangaire mhéadaigh sé faoi 1. Nuair a shroich sé 0xFFFFFFFE, tharla tiomsú, sábháladh an modúl sa tábla feidhme, iompórtáladh isteach i “tosaitheoir” beag é, ónar tháinig an forghníomhú tcg_qemu_tb_exec, agus baineadh an modúl as cuimhne QEMU.

Chun na clasaicí a athinsint, “Crutch, cé mhéad atá fite fuaite sa fhuaim seo do chroí an tairgeora...”. Mar sin féin, bhí an chuimhne ag sceitheadh ​​áit éigin. Ina theannta sin, bhí sé á bhainistiú ag QEMU cuimhne! Bhí cód agam, agus an chéad treoir eile á scríobh agam (bhuel, is é sin, pointeoir), scrios mé an ceann a raibh a nasc san áit seo níos luaithe, ach níor chabhraigh sé seo. I ndáiríre, sa chás is simplí, leithdháileann QEMU cuimhne ag am tosaithe agus scríobhann sé an cód ginte ann. Nuair a ritheann an maolán amach, caitear an cód amach agus tosaítear ar an gcéad cheann eile a scríobh ina áit.

Tar éis dom staidéar a dhéanamh ar an gcód, thuig mé gur lig an cleas leis an uimhir draíochta dom gan teip ar an gcarn scrios trí rud éigin mícheart a shaoradh ar mhaolán neamhthosaithe ar an gcéad phas. Ach cé a athscríobhann an maolán chun m’fheidhm a sheachbhóthar níos déanaí? Mar a chomhairlíonn forbróirí Emscripten, nuair a tháinig fadhb ar bith, iompaigh mé an cód a tháinig as ar ais go dtí an feidhmchlár dúchais, socraigh Mozilla Record-Replay air... Go ginearálta, sa deireadh thuig mé rud simplí: do gach bloc, a struct TranslationBlock lena chur síos. Buille faoi thuairim cén áit... Sin ceart, díreach roimh an mbloc ar dheis sa mhaolán. Agus é seo á bhaint amach, chinn mé éirí as úsáid a bhaint as crutches (ar a laghad roinnt), agus chaith mé amach an uimhir draíochta, agus d'aistrigh mé na focail a bhí fágtha go dtí struct TranslationBlock, ag cruthú liosta aon-nasctha ar féidir a thrasnú go tapa nuair a athshocraítear an taisce aistriúcháin, agus saorfaidh cuimhne.

Fanann roinnt crutches: mar shampla, leideanna marcáilte i maolán an chóid - tá cuid acu go simplí BinaryenExpressionRef, is é sin, féachann siad ar na habairtí is gá a chur go líneach isteach sa bhloc bunúsach a ghintear, is é cuid an coinníoll maidir le haistriú idir BBs, is é cuid an áit le dul. Bhuel, tá bloic ullmhaithe cheana féin le haghaidh Relooper a chaithfear a nascadh de réir na gcoinníollacha. Chun idirdhealú a dhéanamh orthu, úsáidtear an toimhde go bhfuil siad go léir ailínithe le ceithre bheart ar a laghad, ionas gur féidir leat an dá ghiotán suntasach is lú a úsáid go sábháilte don lipéad, ní mór duit ach cuimhneamh é a bhaint más gá. Dála an scéil, úsáidtear lipéid den sórt sin cheana féin i QEMU chun an chúis atá leis an lúb TCG a fhágáil a chur in iúl.

Ag baint úsáide as Binaryen

Tá feidhmeanna i modúil WebAssembly, a bhfuil corp i ngach ceann acu, ar slonn é. Is oibríochtaí unary agus dénártha iad na habairtí, bloic comhdhéanta de liostaí de na habairtí eile, sreabhadh rialaithe, etc. Mar a dúirt mé cheana, eagraítear sreabhadh rialaithe anseo go beacht mar bhrainsí ardleibhéil, lúb, glaonna feidhm, etc. Ní chuirtear argóintí maidir le feidhmeanna ar aghaidh ar an stack, ach go sainráite, díreach mar a dhéantar i JS. Tá athróga domhanda ann freisin, ach níor úsáid mé iad, mar sin ní inseoidh mé duit fúthu.

Tá athróga áitiúla ag feidhmeanna freisin, uimhrithe ó nialas, den chineál: int32 / int64 / snámhphointe / dúbailte. Sa chás seo, is iad na chéad n athróg áitiúil na hargóintí a chuirtear ar aghaidh chuig an bhfeidhm. Tabhair faoi deara le do thoil, cé nach bhfuil gach rud anseo ar leibhéal iomlán íseal ó thaobh an tsreafa rialaithe de, níl an tréith “sínithe/neamhshínithe” ag slánuimhreacha go fóill: braitheann conas a iompraíonn an uimhir ar chód na hoibríochta.

Go ginearálta, soláthraíonn Binaryen C-API simplí: cruthaíonn tú modúl, annsin nathanna a chruthú - unary, dénártha, bloic ó nathanna eile, sreabhadh rialaithe, etc. Ansin cruthaíonn tú feidhm le slonn mar a chorp. Má tá graf trasdula ísealleibhéil agatsa, cosúil liomsa, cabhróidh an chomhpháirt athlúbtha leat. Chomh fada agus a thuigim, is féidir úsáid a bhaint as rialú ardleibhéil ar an sreabhadh forghníomhaithe i mbloc, chomh fada agus nach dtéann sé thar theorainneacha an bhloc - is é sin, is féidir cosán tapa inmheánach a dhéanamh / mall. cosán brainseach taobh istigh den chód próiseála taisce TLB ionsuite, ach gan cur isteach ar an sreabhadh rialaithe "seachtrach". Nuair a shaorann tú athlúbóir, saortar a bhloic; nuair a shaorann tú modúl, imíonn na habairtí, na feidhmeanna, srl. a leithdháiltear air. réimse.

Mar sin féin, más mian leat cód a léirmhíniú ar an eitilt gan ateangaire a chruthú agus a scriosadh gan ghá, b'fhéidir go mbeadh ciall leis an loighic seo a chur isteach i gcomhad C++, agus as sin bainistiú díreach a dhéanamh ar API C++ iomlán na leabharlainne, ag seachaint réidh- cumhdaigh déanta.

Mar sin chun an cód atá uait a ghiniúint

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

... má rinne mé dearmad ar rud ar bith, tá brón orm, níl sé seo ach chun an scála a léiriú, agus tá na sonraí sa doiciméadú.

Agus anois tosaíonn an crack-fex-pex, rud mar seo:

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

D'fhonn saol QEMU agus JS a nascadh ar bhealach éigin agus ag an am céanna rochtain a fháil ar na feidhmeanna tiomsaithe go tapa, cruthaíodh sraith (tábla feidhmeanna le haghaidh allmhairiú isteach sa tosaitheoir), agus cuireadh na feidhmeanna ginte ann. Chun an t-innéacs a ríomh go tapa, baineadh úsáid as innéacs an bhloc aistrithe focal náid mar é ar dtús, ach ansin thosaigh an t-innéacs a ríomhadh ag baint úsáide as an bhfoirmle seo ag luí isteach sa réimse i struct TranslationBlock.

Dála an scéil, taispeána (le ceadúnas murky faoi láthair) ní oibríonn ach go breá i Firefox. Bhí forbróirí Chrome ar bhealach nach bhfuil réidh ar an bhfíric go mbeadh duine ag iarraidh níos mó ná míle cás de mhodúil WebAssembly a chruthú, agus mar sin leithdháil siad gigabyte de spás seoltaí fíorúil do gach ...

Sin go léir faoi láthair. B’fhéidir go mbeidh alt eile ann má tá suim ag éinne ann. Eadhon, tá fós ar a laghad amháin déan gléasanna bloc a oibriú. B’fhéidir go mbeadh sé ciall freisin tiomsú modúil WebAssembly a dhéanamh neamhshioncrónach, mar is gnách i ndomhan JS, ós rud é go bhfuil ateangaire fós in ann é seo go léir a dhéanamh go dtí go mbeidh an modúl dúchais réidh.

Mar fhocal scoir: tá dénártha curtha le chéile agat ar ailtireacht 32-giotán, ach tá an cód, trí oibríochtaí cuimhne, ag dreapadh ó Binaryen, áit éigin ar an gcruach, nó áit éigin eile sa 2 GB uachtarach den spás seoladh 32-giotán. Is í an fhadhb atá ann, ó thaobh Binaryen de, go bhfuil sé seo ag teacht ar sheoladh ró-mhór dá bharr. Conas a fháil timpeall seo?

Ar bhealach admin

Ní dhearna mé tástáil air seo ar deireadh, ach ba é an chéad smaoineamh a bhí agam ná “Cad é má chuir mé Linux 32-giotán isteach?” Ansin beidh an chuid uachtarach den spás seoladh á áitiú ag an eithne. Is í an t-aon cheist ná cé mhéad a bheidh áitithe: 1 nó 2 Gb.

Ar bhealach ríomhchláraitheora (rogha do chleachtóirí)

Séidfimid mboilgeog ag barr an spáis seoltaí. Ní thuigim féin cén fáth a n-oibríonn sé - ann cheana féin caithfidh cruach a bheith ann. Ach “is cleachtóirí muid: oibríonn gach rud dúinne, ach níl a fhios ag éinne cén fáth...”

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

... is fíor nach bhfuil sé ag luí le Valgrind, ach, go fortunately, cuireann Valgrind féin gach duine as sin go héifeachtach :)

B'fhéidir go dtabharfaidh duine éigin míniú níos fearr ar conas a oibríonn an cód mianach seo ...

Foinse: will.com

Add a comment