QEMU.js: a-nis trom agus le WASM

Uair dhe na h-uairean cho-dhùin mi airson spòrs dearbhadh air neo-sheasmhachd a’ phròiseis agus ionnsaich mar a ghineas tu JavaScript (nas mionaidiche, Asm.js) bho chòd inneal. Chaidh QEMU a thaghadh airson an deuchainn, agus beagan ùine às deidh sin chaidh artaigil a sgrìobhadh air Habr. Anns na beachdan chaidh comhairle a thoirt dhomh am pròiseact ath-dhèanamh ann an WebAssembly, agus eadhon mo dhreuchd a leigeil dheth cha mhòr deiseil Cha robh mi dòigh air choireigin ag iarraidh a’ phròiseict... Bha an obair a’ dol air adhart, ach gu math slaodach, agus a-nis, o chionn ghoirid nochd san artaigil sin aithris air a’ chuspair “Mar sin ciamar a thàinig e gu crìch?” Mar fhreagairt don fhreagairt mhionaideach agam, chuala mi “Tha seo coltach ri artaigil.” Uill, mas urrainn dhut, bidh artaigil ann. Is dòcha gum bi cuideigin ga fhaighinn feumail. Às an seo ionnsaichidh an leughadair cuid de dh’ fhìrinnean mu dhealbhadh backends gineadh còd QEMU, a bharrachd air mar a sgrìobhas tu inneal-cruinneachaidh Just-in-Time airson tagradh lìn.

gnìomhan

Leis gu robh mi mu thràth air ionnsachadh mar a nì mi “dòigh air choireigin” port QEMU gu JavaScript, an turas seo chaidh co-dhùnadh a dhèanamh gu ciallach agus gun a bhith ag ath-aithris seann mhearachdan.

Mearachd àireamh a h-aon: meur bho sgaoileadh puing

B ’e a’ chiad mhearachd a bh ’agam a bhith a’ forc mo dhreach bhon dreach shuas an abhainn 2.4.1. An uairsin bha e coltach gur e deagh bheachd a bh’ ann dhomh: ma tha sgaoileadh puing ann, is dòcha gu bheil e nas seasmhaiche na 2.4 sìmplidh, agus eadhon nas motha mar sin am meur master. Agus leis gu robh mi an dùil tomhas math de na mialan agam fhìn a chuir ris, cha robh feum agam air duine sam bith eile idir. Is dòcha gur ann mar sin a thionndaidh e a-mach. Ach seo an rud: chan eil QEMU a’ seasamh fhathast, agus aig àm air choreigin dh’ ainmich iad eadhon optimization den chòd a chaidh a chruthachadh le 10 sa cheud. An seo feumaidh sinn adhartas a dhèanamh: air sgàth nàdar aon-snàithle QEMU.js agus leis nach eil an QEMU tùsail a’ ciallachadh nach eil ioma-snàithlean ann (is e sin, an comas grunn shlighean còd neo-cheangailte obrachadh aig an aon àm, agus chan e dìreach “cleachd a h-uile kernels”) a tha deatamach air a shon, is e prìomh dhleastanasan snàithleanan a bha agam ri “tionndadh a-mach” airson a bhith comasach air gairm bhon taobh a-muigh. Chruthaich seo cuid de dhuilgheadasan nàdarra rè an aonaidh. Ach, an fhìrinn gu bheil cuid de na h-atharrachaidhean bhon mheur master, leis an do dh'fheuch mi ris a 'chòd agam a chur còmhla, cuideachd air an taghadh anns an fhoillseachadh puing (agus mar sin anns a' mheur agam) cuideachd is dòcha nach biodh e air goireas a bharrachd.

San fharsaingeachd, cho-dhùin mi gu bheil e fhathast ciallach am prototype a thilgeil a-mach, a chuir às a chèile airson pàirtean agus dreach ùr a thogail bhon fhìor thoiseach stèidhichte air rudeigin nas ùire agus a-nis bho master.

Mearachd àireamh a dhà: modh-obrach TLP

Gu dearbh, chan e mearachd a tha seo, san fharsaingeachd, chan eil ann ach feart de bhith a’ cruthachadh pròiseact ann an suidheachaidhean de mhì-thuigse iomlan air an dà chuid “càite agus ciamar a ghluaiseas sinn?” agus san fharsaingeachd “an ruig sinn ann?” Anns na suidheachaidhean seo prògramadh sgoinneil bha e na roghainn reusanta, ach, gu nàdarra, cha robh mi airson a dhèanamh a-rithist gun fheum. An turas seo bha mi airson a dhèanamh gu ciallach: geallaidhean atamach, atharraichean còd mothachail (agus gun a bhith “a’ ceangal charactaran air thuaiream ri chèile gus an cuir e ri chèile (le rabhaidhean)", mar a thuirt Linus Torvalds aon uair mu dheidhinn cuideigin, a rèir Wikiquote), msaa.

Mearachd àireamh a trì: faighinn a-steach don uisge gun fhios don fhadhail

Chan eil mi fhathast air faighinn cuidhteas seo gu tur, ach a-nis tha mi air co-dhùnadh gun a bhith a’ leantainn an t-slighe as lugha an aghaidh idir, agus a dhèanamh “mar inbheach,” is e sin, sgrìobh mo backend TCG bhon toiseach, gus nach feumaidh mi a ràdh nas fhaide air adhart, “Tha, tha seo gu dearbh, slaodach, ach chan urrainn dhomh smachd a chumail air a h-uile càil - sin mar a tha TCI air a sgrìobhadh…” A bharrachd air an sin, bha seo an toiseach a’ coimhead mar fhuasgladh follaiseach, bhon uair sin Bidh mi a’ cruthachadh còd binary. Mar a chanas iad, “Chruinnich Ghentу, ach chan e sin”: tha an còd, gu dearbh, dà-chànanach, ach chan urrainnear smachd a ghluasad thuige - feumaidh e a bhith air a phutadh gu soilleir a-steach don bhrobhsair airson a chuir ri chèile, a ’leantainn gu rud sònraichte bhon t-saoghal JS, a dh’ fheumas fhathast bhith air a shàbhaladh an àiteigin. Ach, a thaobh ailtireachd àbhaisteach RISC, cho fad ‘s a tha mi a’ tuigsinn, is e suidheachadh àbhaisteach am feum air an tasgadan stiùiridh ath-nuadhachadh gu soilleir airson còd ath-nuadhaichte - mura h-e seo a tha a dhìth oirnn, an uairsin, co-dhiù, tha e faisg. A bharrachd air an sin, bhon oidhirp mu dheireadh agam, dh’ ionnsaich mi nach eil coltas gu bheil smachd air a ghluasad gu meadhan a ’bhloc eadar-theangachaidh, agus mar sin chan eil feum againn air bytecode air a mhìneachadh bho chothromachadh sam bith, agus is urrainn dhuinn dìreach a ghineadh bhon ghnìomh air TB .

Thàinig iad agus bhreab iad

Ged a thòisich mi ag ath-sgrìobhadh a’ chòd air ais san Iuchar, thàinig breab draoidheachd suas gun mhothachadh: mar as trice bidh litrichean bho GitHub a’ tighinn mar fhiosan mu fhreagairtean do dh’ iarrtasan Cùisean is Tarraing, ach an seo, gu h-obann iomradh anns an t-snàthainn Binaryen mar backend qemu anns a’ cho-theacsa, “Rinn e rudeigin mar sin, is dòcha gun can e rudeigin.” Bha sinn a’ bruidhinn mu bhith a’ cleachdadh an leabharlann co-cheangailte aig Emscripten Binaryen gus WASM JIT a chruthachadh. Uill, thuirt mi gu bheil cead Apache 2.0 agad an sin, agus tha QEMU gu h-iomlan air a chuairteachadh fo GPLv2, agus chan eil iad gu math co-chòrdail. Gu h-obann thionndaidh e a-mach gum faod cead a bhith ceartaich e dòigh air choireigin (Chan eil fios agam: is dòcha atharraich e, is dòcha cead dùbailte, is dòcha rudeigin eile ...). Rinn seo, gu dearbh, mi toilichte, oir ron àm sin bha mi air sùil gheur a chumail air cruth binary WebAssembly, agus bha mi dòigh air choireigin brònach agus do-thuigsinn. Bha leabharlann ann cuideachd a bhiodh ag ithe na blocaichean bunaiteach leis a’ ghraf gluasaid, a’ toirt a-mach an bytecode, agus eadhon ga ruith san eadar-theangair fhèin, nam biodh sin riatanach.

An uairsin bha barrachd ann litir air liosta puist QEMU, ach tha seo nas motha mun cheist, “Cò a tha feumach air co-dhiù?” Agus tha e gu h-obann, thionndaidh e a-mach gu robh feum air. Aig a 'char as lugha, faodaidh tu na cothroman cleachdaidh a leanas a bhriseadh còmhla, ma dh' obraicheas e nas luaithe no nas luaithe:

  • a’ cur air bhog rudeigin foghlaim gun stàladh sam bith idir
  • virtualization air iOS, far, a rèir fathannan, is e einnsean JS an aon iarrtas aig a bheil còir air gineadh còd air an itealan (a bheil seo fìor?)
  • taisbeanadh mion-OS - aon-fhillte, togte, a h-uile seòrsa firmware, msaa ...

Feartan Runtime Browser

Mar a thuirt mi mu thràth, tha QEMU ceangailte ri multithreading, ach chan eil e aig a’ bhrobhsair. Uill, is e sin, chan e... An toiseach cha robh e ann idir, an uairsin nochd WebWorkers - cho fad 's a tha mi a' tuigsinn, tha seo ioma-snàithlean stèidhichte air teachdaireachd a 'dol seachad às aonais caochladairean co-roinnte. Gu nàdarra, bidh seo a’ cruthachadh dhuilgheadasan mòra nuair a thathar a’ giùlain còd a th’ ann mar-thà stèidhichte air a’ mhodail cuimhne co-roinnte. An uairsin, fo chuideam poblach, chaidh a chuir an gnìomh cuideachd fon ainm SharedArrayBuffers. Chaidh a thoirt a-steach mean air mhean, chomharraich iad a chuir air bhog ann an diofar bhrobhsairean, an uairsin chomharraich iad a’ Bhliadhn ’Ùr, agus an uairsin Meltdown… Às deidh sin thàinig iad chun cho-dhùnadh gun robh an tomhas ùine garbh no garbh, ach le cuideachadh bho chuimhne roinnte agus a snàthainn ag àrdachadh a’ chunntair, tha e uile mar an ceudna obraichidh e a-mach gu math ceart. Mar sin chuir sinn à comas multithreading le cuimhne co-roinnte. Tha e coltach gun do thionndaidh iad air ais e nas fhaide air adhart, ach, mar a dh'fhàs e soilleir bhon chiad dheuchainn, tha beatha às aonais, agus ma tha, feuchaidh sinn ri dhèanamh gun a bhith an urra ri ioma-snàthainn.

Is e an dàrna feart nach eil e comasach làimhseachadh ìre ìosal leis a’ chruach: chan urrainn dhut dìreach an co-theacsa gnàthach a ghabhail, a shàbhaladh agus atharrachadh gu fear ùr le stac ùr. Tha an stac gairm air a riaghladh le inneal brìgheil JS. Bhiodh e coltach, dè an duilgheadas a th’ ann, leis gu bheil sinn fhathast air co-dhùnadh na sruthan a bh’ ann roimhe a riaghladh gu tur le làimh? Is e an fhìrinn gu bheil bloc I / O ann an QEMU air a chuir an gnìomh tro coroutines, agus seo far an tigeadh làimhseachadh stac aig ìre ìosal gu feum. Gu fortanach, tha inneal ann an Emscipten mu thràth airson obrachaidhean asyncronach, eadhon dhà: Sioncronaich и Eadar-theangair. Bidh a’ chiad fhear ag obair tro bloat mòr anns a’ chòd JavaScript a chaidh a chruthachadh agus chan eil e a’ faighinn taic tuilleadh. Is e an dàrna fear an “dòigh cheart” gnàthach agus bidh e ag obair tro ghineadh bytecode airson an eadar-theangair dùthchasach. Bidh e ag obair, gu dearbh, gu slaodach, ach chan eil e a 'toirt buaidh air a' chòd. Fìor, dh’ fheumadh taic a thoirt do coroutines airson an uidheamachd seo gu neo-eisimeileach (bha coroutines sgrìobhte mu thràth airson Asyncify agus chaidh timcheall air an aon API a chuir an gnìomh airson Emterpreter, cha robh agad ach an ceangal).

Aig an àm seo, chan eil mi fhathast air a 'chòd a roinn ann an aon a chaidh a chur ri chèile ann an WASM agus air a mhìneachadh le bhith a' cleachdadh Emterpreter, agus mar sin chan eil innealan bloca ag obair fhathast (faic san ath shreath, mar a chanas iad ...). Is e sin, aig a’ cheann thall bu chòir dhut rudeigin mar an rud èibhinn èibhinn seo fhaighinn:

  • bloc eadar-mhìneachaidh I/O. Uill, an robh dùil agad dha-rìribh NVMe aithris le coileanadh dùthchasach? 🙂
  • prìomh chòd QEMU air a chur ri chèile gu staitigeach (eadar-theangaiche, innealan emulated eile, msaa.)
  • còd aoighean air a chuir ri chèile gu dinamach a-steach do WASM

Feartan stòran QEMU

Mar is dòcha gu bheil thu air smaoineachadh mu thràth, tha an còd airson a bhith ag aithris ailtireachd aoighean agus an còd airson stiùireadh inneal aoigheachd a ghineadh air an sgaradh ann an QEMU. Gu dearbh, tha e eadhon beagan nas duilghe:

  • tha ailtireachd aoighean ann
  • tha luathaichean, is e sin, KVM airson virtualization bathar-cruaidh air Linux (airson siostaman aoighean is aoigheachd a tha co-chosmhail ri chèile), TCG airson gineadh còd JIT an àite sam bith. A’ tòiseachadh le QEMU 2.9, nochd taic airson inbhe virtualization bathar-cruaidh HAXM air Windows (mion-fhiosrachadh)
  • ma thèid TCG a chleachdadh agus chan e virtualization bathar-cruaidh, tha taic gineadh còd air leth aige airson gach ailtireachd aoigheachd, a bharrachd air an eadar-theangair uile-choitcheann
  • ... agus timcheall air seo - iomaill emulated, eadar-aghaidh cleachdaiche, imrich, ath-chluich chlàran, msaa.

Co-dhiù, an robh fios agad: Faodaidh QEMU aithris a dhèanamh chan ann a-mhàin air a’ choimpiutair gu lèir, ach cuideachd am pròiseasar airson pròiseas cleachdaiche fa leth anns an kernel aoigheachd, a bhios air a chleachdadh, mar eisimpleir, leis an fhuzzer AFL airson ionnsramaid dàna. Is dòcha gum biodh cuideigin airson am modh-obrachaidh seo de QEMU a phortadh gu JS? 😉

Coltach ris a’ mhòr-chuid de bhathar-bog an-asgaidh o chionn fhada, tha QEMU air a thogail tron ​​​​ghairm configure и make. Canaidh sinn gun co-dhùin thu rudeigin a chuir ris: backend TCG, buileachadh snàithlean, rudeigin eile. Na dèan cabhag gus a bhith toilichte / uabhas (fo-loidhne mar a bhios iomchaidh) nuair a tha thu an dùil conaltradh le Autoconf - gu dearbh, configure Tha e coltach gu bheil QEMU's fèin-sgrìobhte agus nach eil e air a chruthachadh bho rud sam bith.

Lìn eile

Mar sin dè an t-ainm a th’ air an rud seo WebAssembly (aka WASM)? Tha seo na àite Asm.js, gun a bhith a’ leigeil a-mach gur e còd JavaScript dligheach a th’ ann tuilleadh. Air an làimh eile, tha e dìreach dà-chànanach agus làn-leasaichte, agus eadhon dìreach a bhith a ’sgrìobhadh integer a-steach chan eil e gu math sìmplidh: airson compactness, tha e air a stòradh ann an cruth LEB128.

Is dòcha gu bheil thu air cluinntinn mun algairim ath-chuairteachaidh airson Asm.js - is e seo ath-nuadhachadh stiùireadh smachd sruthadh “àrd-ìre” (is e sin, ma tha - an uairsin, lùban, msaa), airson a bheil einnseanan JS air an dealbhadh, bho an LLVM IR aig ìre ìosal, nas fhaisge air còd an inneil a chuir am pròiseasar gu bàs. Gu nàdarra, tha riochdachadh eadar-mheadhanach QEMU nas fhaisge air an dàrna fear. Bhiodh e coltach gur e seo, bytecode, deireadh a’ chràdh... Agus an uairsin tha blocaichean ann, ma tha - an uairsin-eile agus lùban!..

Agus is e seo adhbhar eile carson a tha Binaryen feumail: faodaidh e gu nàdarra gabhail ri blocaichean àrd-ìre faisg air na bhiodh air a stòradh ann an WASM. Ach faodaidh e cuideachd còd a dhèanamh bho ghraf de bhlocaichean bunaiteach agus eadar-ghluasadan eatorra. Uill, tha mi air a ràdh mar-thà gu bheil e a’ falach cruth stòraidh WebAssembly air cùl an API goireasach C/C ++.

TCG (gineadair còd beag)

GTC bha bho thùs backend airson an compiler C. An uairsin, a rèir coltais, cha b’ urrainn dha seasamh an aghaidh a ’cho-fharpais le GCC, ach aig a’ cheann thall lorg e àite ann an QEMU mar inneal gineadh còd airson an àrd-ùrlar aoigheachd. Tha backend TCG ann cuideachd a ghineas beagan bytecode eas-chruthach, a thèid a chuir gu bàs sa bhad leis an eadar-theangair, ach chuir mi romham a chleachdadh an turas seo. Ach, leis gu bheil e comasach mar-thà ann an QEMU gluasad gu TB a chaidh a chruthachadh tron ​​​​ghnìomh tcg_qemu_tb_exec, thionndaidh e a-mach gu bhith glè fheumail dhomh.

Gus backend TCG ùr a chur ri QEMU, feumaidh tu fo-eòlaire a chruthachadh tcg/<имя архитектуры> (anns a’ chùis seo, tcg/binaryen), agus tha dà fhaidhle ann: tcg-target.h и tcg-target.inc.c и clàraich tha e mu dheidhinn configure. Faodaidh tu faidhlichean eile a chuir ann, ach, mar a dh’ aithnicheas tu bho ainmean an dithis seo, bidh iad le chèile air an toirt a-steach am badeigin: aon mar fhaidhle cinn cunbhalach (tha e air a ghabhail a-steach ann an tcg/tcg.h, agus tha am fear sin mu thràth ann am faidhlichean eile anns na clàran tcg, accel agus chan e a-mhàin), am fear eile - a-mhàin mar chriomag còd a-steach tcg/tcg.c, ach tha cothrom aige air na gnìomhan statach aige.

A’ co-dhùnadh gun cuireadh mi seachad cus ùine air sgrùdaidhean mionaideach air mar a tha e ag obair, cha do rinn mi ach leth-bhreac de na “cnàimhneachan” den dà fhaidhle seo bho bhuileachadh backend eile, a’ nochdadh seo gu h-onarach ann am bann-cinn a’ cheadachais.

faidhl tcg-target.h a’ toirt a-steach suidheachaidhean san fhoirm sa mhòr-chuid #define-s:

  • cia mheud clàr agus dè an leud a tha air an ailtireachd targaid (tha na h-uimhir againn agus a tha sinn ag iarraidh, na tha sinn ag iarraidh - tha a’ cheist nas motha mu na thèid a chruthachadh gu còd nas èifeachdaiche leis a ’bhrobhsair air an ailtireachd“ targaid iomlan " ...)
  • co-thaobhadh stiùireadh aoigheachd: air x86, agus eadhon ann an TCI, chan eil stiùireadh air a cho-thaobhadh idir, ach tha mi a’ dol a chuir a-steach am bufair còd chan e stiùireadh idir, ach comharran gu structaran leabharlann Binaryen, mar sin canaidh mi: 4 bytes
  • dè an stiùireadh roghainneil as urrainn don backend a ghineadh - bidh sinn a’ toirt a-steach a h-uile dad a lorgas sinn ann am Binaryen, leig leis an luathadair an còrr a bhriseadh gu feadhainn nas sìmplidhe fhèin
  • Dè an tuairmse de mheud an tasgadan TLB a dh’ iarr an backend. Is e an fhìrinn gu bheil a h-uile dad ann an QEMU dona: ged a tha gnìomhan cuideachaidh ann a bhios a’ coileanadh luchd / stòr a’ toirt aire don MMU aoigh (càit am biodh sinn às aonais a-nis?), bidh iad a’ sàbhaladh an tasgadan eadar-theangachaidh aca ann an cruth structair, an a tha goireasach airson a ghiullachd gu dìreach ann am blocaichean craolaidh. Is e a’ cheist, dè an cothromachadh san structar seo a tha air a phròiseasadh as èifeachdaiche le sreath bheag agus luath de òrdughan?
  • an seo faodaidh tu adhbhar clàr glèidhte no dhà a chleachdadh, leigeil le TB a ghairm tro ghnìomh agus cunntas a thoirt gu roghnach air dhà no dhà inline- gnìomhan mar flush_icache_range (ach chan e seo ar cùis)

faidhl tcg-target.inc.c, gu dearbh, mar as trice tòrr nas motha ann am meud agus tha grunn ghnìomhan èigneachail ann:

  • tòiseachadh, a’ gabhail a-steach cuingeachaidhean air an urrainn stiùireadh obrachadh air dè na h-obraichean. Air a chopaigeadh leam gu soilleir bho chùl-raon eile
  • gnìomh a bheir aon stiùireadh bytecode a-staigh
  • Faodaidh tu cuideachd gnìomhan taice a chuir an seo, agus faodaidh tu cuideachd gnìomhan statach a chleachdadh bho tcg/tcg.c

Airson mi fhìn, thagh mi an ro-innleachd a leanas: anns a 'chiad fhaclan den ath bhloc eadar-theangachaidh, sgrìobh mi sìos ceithir puingean: comharra tòiseachaidh (luach sònraichte faisg air làimh 0xFFFFFFFF, a cho-dhùin staid làithreach an TB), co-theacsa, modal gineadh, agus àireamh draoidheachd airson debugging. An toiseach chaidh an comharra a chuir a-steach 0xFFFFFFFF - ncàite n - àireamh bheag dearbhach, agus gach uair a chaidh a chur gu bàs tron ​​​​eadar-theangair mheudaich e le 1. Nuair a ràinig e 0xFFFFFFFE, chaidh an cur ri chèile, chaidh am modal a shàbhaladh anns a’ chlàr gnìomh, air a thoirt a-steach do “launcher” beag, às an deach an cur gu bàs tcg_qemu_tb_exec, agus chaidh am modal a thoirt air falbh bho chuimhne QEMU.

Gus ath-sgrìobhadh a dhèanamh air na clasaichean clasaigeach, “Crutch, dè an ìre a tha eadar-fhighte san fhuaim seo airson cridhe an neach-brathaidh...”. Ach, bha an cuimhne ag aoidion an àiteigin. A bharrachd air an sin, b’ e cuimhne a bha air a riaghladh le QEMU! Bha còd agam, nuair a bha mi a’ sgrìobhadh an ath stiùireadh (uill, is e sin, puing), a chuir às don fhear aig an robh ceangal san àite seo na bu thràithe, ach cha do chuidich seo. Gu fìrinneach, anns a ’chùis as sìmplidh, bidh QEMU a’ riarachadh cuimhne aig toiseach tòiseachaidh agus a ’sgrìobhadh a’ chòd a chaidh a chruthachadh an sin. Nuair a ruitheas am bufair a-mach, thèid an còd a thilgeil a-mach agus tòisichidh an ath fhear air a sgrìobhadh na àite.

An dèidh sgrùdadh a dhèanamh air a 'chòd, thuig mi gun robh an cleas leis an àireamh draoidheachd a' leigeil leam gun a bhith a 'fàilligeadh air sgrios le bhith a' saoradh rudeigin ceàrr air bufair neo-aithnichte air a 'chiad pas. Ach cò a bhios ag ath-sgrìobhadh am bufair gus an gnìomh agam a sheachnadh nas fhaide air adhart? Mar a tha luchd-leasachaidh Emscripten a’ comhairleachadh, nuair a ruith mi a-steach do dhuilgheadas, ghiùlain mi an còd a thàinig às air ais chun aplacaid dhùthchasach, suidhich Mozilla Record-Replay air... San fharsaingeachd, aig a’ cheann thall, thuig mi rud sìmplidh: airson gach bloca, a struct TranslationBlock leis an tuairisgeul aige. Dèan tomhas càite... Tha sin ceart, dìreach ron bhloc dìreach sa bhufair. Le seo a thoirt gu buil, chuir mi romhpa stad a chur air cleachdadh crutches (co-dhiù cuid), agus dìreach thilg mi a-mach an àireamh draoidheachd, agus ghluais mi na faclan a bha air fhàgail gu struct TranslationBlock, a’ cruthachadh liosta le ceangal singilte a ghabhas a dhol tarsainn gu sgiobalta nuair a thèid an tasgadan eadar-theangachaidh ath-shuidheachadh, agus cuimhne a shaoradh.

Tha cuid de bhratagan fhathast ann: mar eisimpleir, comharran comharraichte ann am bufair còd - tha cuid dhiubh sìmplidh BinaryenExpressionRef, is e sin, bidh iad a’ coimhead air na h-abairtean a dh’ fheumar a chuir gu sreathach a-steach don bhloc bunaiteach a chaidh a chruthachadh, is e pàirt an suidheachadh airson gluasad eadar BBs, is e pàirt far an tèid thu. Uill, tha blocaichean ullaichte ann mu thràth airson Relooper a dh’ fheumar a cheangal a rèir nan cumhachan. Gus eadar-dhealachadh a dhèanamh orra, thathas a 'cleachdadh a' bharail gu bheil iad uile air an co-thaobhadh le co-dhiù ceithir bytes, gus an urrainn dhut an dà phìos as cudromaiche a chleachdadh gu sàbhailte airson an leubail, feumaidh tu cuimhneachadh gun cuir thu air falbh e ma tha sin riatanach. Air an t-slighe, tha na bileagan sin air an cleachdadh mar-thà ann an QEMU gus an adhbhar airson an lùb TCG fhàgail.

A 'cleachdadh Binaryen

Tha gnìomhan anns na modalan ann an WebAssembly, agus tha corp anns gach fear dhiubh, a tha na dhòigh-labhairt. Is e gnìomhan aonarach agus dà-chànanach a th’ ann an abairtean, blocaichean anns a bheil liostaichean de abairtean eile, sruth smachd, msaa. Mar a thuirt mi mu thràth, tha sruth smachd an seo air a chuir air dòigh gu mionaideach mar mheuran àrd-ìre, lùban, gairmean gnìomh, msaa. Chan eil argamaidean gu gnìomhan air an toirt seachad air a’ chruach, ach gu soilleir, dìreach mar ann an JS. Tha caochladairean cruinneil ann cuideachd, ach cha do chleachd mi iad, agus mar sin chan innis mi dhut mun deidhinn.

Tha caochladairean ionadail aig gnìomhan cuideachd, air an àireamhachadh bho neoni, de sheòrsa: int32 / int64 / fleòdradh / dùbailte. Anns a 'chùis seo, is e a' chiad n caochladair ionadail na h-argamaidean a chaidh a thoirt don ghnìomh. Thoir an aire, ged nach eil a h-uile dad an seo gu tur aig ìre ìosal a thaobh sruthadh smachd, chan eil am feart “soidhnichte / gun ainm” fhathast aig àireamhan iomlan: tha mar a bhios an àireamh gan giùlan fhèin an urra ris a’ chòd obrachaidh.

San fharsaingeachd, tha Binaryen a 'toirt seachad C-API sìmplidh: cruthaichidh tu modal, ann-san cruthaich abairtean - aonarach, dà-chànanach, blocaichean bho abairtean eile, smachd air sruthadh, msaa. An uairsin cruthaichidh tu gnìomh le faireachdainn mar a bhodhaig. Ma tha graf gluasaid ìre ìosal agad fhèin, mar mise, cuidichidh am pàirt relooper thu. Cho fad ‘s a tha mi a’ tuigsinn, tha e comasach smachd àrd-ìre a chleachdadh air an t-sruth cur gu bàs ann am bloc, fhad ‘s nach tèid e seachad air crìochan a’ bhloc - is e sin, tha e comasach slighe luath / slaodach a-staigh a dhèanamh. slighe branrach taobh a-staigh còd giullachd tasgadan TLB a chaidh a thogail a-steach, ach gun a bhith a’ cur bacadh air an t-sruth smachd “taobh a-muigh”. Nuair a shaoras tu relooper, thèid na blocaichean aige a shaoradh; nuair a shaoras tu modal, falbhaidh na h-abairtean, na gnìomhan, msaa a chaidh a thoirt dha raon.

Ach, ma tha thu airson còd a mhìneachadh air an itealan gun a bhith a’ cruthachadh agus a’ cuir às do eisimpleir eadar-mhìneachaidh gun fheum, dh’ fhaodadh gum biodh e ciallach an loidsig seo a chuir ann am faidhle C ++, agus às an sin rian a chumail gu dìreach air C ++ API iomlan an leabharlainn, a’ dol seachad air deiseil- luchd-gleidhidh air an dèanamh.

Mar sin gus an còd a dh 'fheumas tu a chruthachadh

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

... ma dhìochuimhnich mi dad, duilich, tha seo dìreach airson an sgèile a riochdachadh, agus tha am mion-fhiosrachadh anns na sgrìobhainnean.

Agus a-nis tha an crack-fex-pex a’ tòiseachadh, rudeigin 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);

Gus saoghal QEMU agus JS a cheangal ann an dòigh air choreigin agus aig an aon àm faighinn gu na gnìomhan cruinnichte gu sgiobalta, chaidh sreath a chruthachadh (clàr de ghnìomhan airson a thoirt a-steach don lannsair), agus chaidh na gnìomhan gineadh a chuir an sin. Gus an clàr-amais obrachadh a-mach gu sgiobalta, chaidh clàr-amais a’ bhloca eadar-theangachadh facal neoni a chleachdadh an toiseach mar e, ach an uairsin thòisich an clàr-amais a chaidh a thomhas a’ cleachdadh na foirmle seo dìreach a’ freagairt air an raon a-staigh. struct TranslationBlock.

Air an t-slighe, demo (le cead meallta an-dràsta) dìreach ag obair gu math ann am Firefox. Bha luchd-leasachaidh Chrome dòigh air choireigin nach eil deiseil leis an fhìrinn gum biodh cuideigin airson còrr air mìle eisimpleir de mhodalan WebAssembly a chruthachadh, agus mar sin cha do chuir iad ach gigabyte de àite seòlaidh brìgheil airson gach ...

Tha sin uile airson a-nis. Is dòcha gum bi artaigil eile ann ma tha ùidh aig duine sam bith. Is e sin, tha fhathast co-dhiù dìreach toirt air innealan bloca obrachadh. Is dòcha gum biodh e ciallach cuideachd cruinneachadh de mhodalan WebAssembly a dhèanamh asyncronach, mar a tha àbhaisteach ann an saoghal JS, leis gu bheil eadar-theangair ann fhathast as urrainn seo a dhèanamh gus am bi am modal dùthchasach deiseil.

Mu dheireadh tòimhseachan: tha thu air binary a chuir ri chèile air ailtireachd 32-bit, ach tha an còd, tro ghnìomhachd cuimhne, a’ dìreadh bho Binaryen, an àiteigin air a ’chruach, no an àiteigin eile anns an 2 GB gu h-àrd den àite seòlaidh 32-bit. Is e an duilgheadas a th ’ann, bho shealladh Binaryen gu bheil seo a’ faighinn cothrom air seòladh ro mhòr a thig às. Ciamar a gheibh thu timcheall air seo?

Ann an dòigh admin

Cha do rinn mi deuchainn air seo mu dheireadh, ach b’ e a ’chiad bheachd a bh’ agam “Dè ma chuir mi a-steach 32-bit Linux?” An uairsin bidh am pàirt àrd den àite seòlaidh air a ghabhail thairis leis an kernel. Is e an aon cheist cia mheud a bhios ann: 1 no 2 Gb.

Ann an dòigh phrogramaiche (roghainn airson cleachdaichean)

Sèididh sinn builgean aig mullach an àite seòlaidh. Chan eil mi fhìn a’ tuigsinn carson a tha e ag obair - sin mar-thà feumaidh cruach a bhith ann. Ach “tha sinn nar cleachdaichean: bidh a h-uile dad ag obair dhuinne, ach chan eil fios aig duine carson...”

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

tha e fìor nach eil e co-chòrdail ri Valgrind, ach, gu fortanach, tha Valgrind fhèin gu math èifeachdach a’ putadh a h-uile duine a-mach às an sin :)

Is dòcha gun toir cuideigin mìneachadh nas fheàrr air mar a tha an còd seo agam ag obair ...

Source: www.habr.com

Cuir beachd ann