QEMU.js: yanzu mai tsanani kuma tare da WASM

A wani lokaci na yanke shawara don nishaɗi tabbatar da jujjuyawar tsarin kuma koyi yadda ake ƙirƙirar JavaScript (mafi daidai, Asm.js) daga lambar injin. An zaɓi QEMU don gwajin, kuma wani lokaci daga baya an rubuta labarin akan Habr. A cikin maganganun an shawarce ni da in sake yin aikin a cikin WebAssembly, har ma da barin kaina kusan gamawa Na ko ta yaya ba na son aikin ... Aikin yana ci gaba, amma a hankali sosai, kuma yanzu, kwanan nan a cikin wannan labarin ya bayyana. sharhin a kan batun "To ta yaya duk ya ƙare?" Don amsa dalla-dalla na amsa, na ji "Wannan yana kama da labarin." To, idan za ku iya, za a sami labarin. Wataƙila wani zai same shi da amfani. Daga ciki mai karatu zai koyi wasu bayanai game da ƙirar QEMU code backends, da kuma yadda ake rubuta mai tara lokaci-lokaci don aikace-aikacen yanar gizo.

ayyuka

Tun da na riga na koyi yadda ake "ko ta yaya" tashar jiragen ruwa ta QEMU zuwa JavaScript, wannan lokacin an yanke shawarar yin shi cikin hikima kuma kada a maimaita kuskuren tsofaffi.

Kuskuren lamba ɗaya: reshe daga sakin batu

Kuskure na na farko shine na cire sigar tawa daga sigar sama ta 2.4.1. Sa'an nan ya zama a gare ni kyakkyawan ra'ayi: idan sakin batu ya kasance, to tabbas ya fi kwanciyar hankali fiye da 2.4 mai sauƙi, har ma fiye da haka reshe. master. Kuma tun da na yi shirin ƙara daidai adadin kurakurai na, ba na buƙatar wani ko kaɗan. Watakila haka abin ya kasance. Amma ga abu: QEMU ba ta tsaya cik ba, kuma a wani lokaci har ma sun sanar da inganta lambar da aka samar da kashi 10. "Ee, yanzu zan daskare," Na yi tunani kuma na rushe. Anan muna buƙatar yin digression: saboda yanayin QEMU.js guda ɗaya da kuma gaskiyar cewa QEMU na asali baya nuna rashi na multithreading (wato, ikon yin aiki tare da hanyoyi da yawa marasa alaƙa, da ba kawai "amfani da duk kernels") yana da mahimmanci a gare shi, manyan ayyukan zaren dole ne in "juya shi" don samun damar yin kira daga waje. Wannan ya haifar da wasu matsaloli na halitta yayin haɗuwa. Koyaya, gaskiyar cewa wasu canje-canje daga reshe master, wanda na yi ƙoƙari na haɗa lambar tawa, an kuma zaɓi ceri a cikin sakin layi (sabili da haka a cikin reshe na) kuma mai yiwuwa ba zai ƙara dacewa ba.

Gabaɗaya, na yanke shawarar cewa har yanzu yana da ma'ana don jefar da samfurin, rarraba shi don sassa da gina sabon sigar daga karce dangane da wani abu mai sabo kuma yanzu daga master.

Kuskure lamba biyu: Hanyar TLP

A zahiri, wannan ba kuskure ba ne, gabaɗaya, kawai sifa ce ta ƙirƙirar aikin a cikin yanayin cikakkiyar rashin fahimtar duka biyu "inda kuma yadda za a matsa?" kuma gaba ɗaya "za mu isa can?" A cikin wadannan yanayi m shirye-shirye zaɓi ne ingantacce, amma, a zahiri, ba na son maimaita shi ba dole ba. A wannan lokacin ina so in yi shi cikin hikima: Atomatik ya aikata, canje-canjen lambar sani (kuma ba "ƙirƙira bazuwar haruffa tare har sai ya tattara (tare da gargaɗi)", kamar yadda Linus Torvalds ya taɓa faɗi game da wani, a cewar Wikiquote), da sauransu.

Kuskure lamba uku: shiga cikin ruwa ba tare da sanin ford

Har yanzu ban rabu da wannan gaba ɗaya ba, amma yanzu na yanke shawarar ba zan bi hanyar juriya ba kwata-kwata, kuma in yi shi “a matsayina na babba,” wato, rubuta bayanan baya na TCG daga karce, don kada dole in ce daga baya, "Ee, wannan ba shakka, sannu a hankali, amma ba zan iya sarrafa komai ba - haka ake rubuta TCI..." Bugu da ƙari, wannan da farko ya zama kamar mafita a bayyane, tun da Ina samar da lambar binary. Kamar yadda suke cewa, "Ghent ya taruу, amma ba wannan ba": lambar, ba shakka, binary ne, amma ba za a iya canja wurin sarrafawa kawai zuwa gare shi ba - dole ne a tura shi a fili a cikin mai bincike don haɗawa, wanda ya haifar da wani abu daga duniyar JS, wanda har yanzu yana buƙatar. sami ceto wani wuri. Koyaya, akan tsarin gine-ginen RISC na yau da kullun, gwargwadon yadda na fahimta, yanayi na yau da kullun shine buƙatar sake saita cache na koyarwa don lambar da aka sabunta - idan wannan ba shine abin da muke buƙata ba, to, a kowane hali, yana kusa. Bugu da kari, daga yunƙurin da na yi na ƙarshe, na koyi cewa da alama ba a canja wurin sarrafawa zuwa tsakiyar toshewar fassarar ba, don haka ba ma buƙatar ainihin fassarar bytecode daga kowane juzu'i, kuma za mu iya samar da shi kawai daga aikin akan TB. .

Suka zo suka yi ta harbi

Ko da yake na fara sake rubuta lambar a watan Yuli, bugun sihiri ya taso ba tare da an gane shi ba: yawanci haruffa daga GitHub suna zuwa azaman sanarwa game da martani ga batutuwa da buƙatun ja, amma a nan, ba zato ba tsammani ambaton a zaren Binaryen a matsayin qemu baya a cikin mahallin, "Ya yi wani abu kamar haka, watakila zai ce wani abu." Muna magana ne game da amfani da ɗakin karatu mai alaƙa da Emscripten Binaryen don ƙirƙirar WASM JIT. To, na ce kuna da lasisin Apache 2.0 a can, kuma QEMU gabaɗaya ana rarraba su ƙarƙashin GPLv2, kuma ba su dace sosai ba. Nan da nan ya juya cewa lasisi na iya zama gyara shi ko ta yaya (Ban sani ba: watakila canza shi, watakila biyu lasisi, watakila wani abu dabam ...). Wannan, ba shakka, ya faranta min rai, domin a lokacin na riga na duba sosai tsarin binary WebAssembly, kuma na kasance ko ta yaya baƙin ciki da rashin fahimta. Har ila yau, akwai ɗakin karatu wanda zai cinye ainihin tubalan tare da jadawali na canji, samar da bytecode, har ma da sarrafa shi a cikin mai fassarar kanta, idan ya cancanta.

Sa'an nan kuma akwai ƙari harafi akan jerin aikawasiku ta QEMU, amma wannan shine ƙarin game da tambayar, "Wane ne yake buƙata ta wata hanya?" Kuma shi ne ba zato ba tsammani, ya zama dole. Aƙalla, zaku iya goge abubuwan damar amfani masu zuwa tare, idan yana aiki fiye ko žasa da sauri:

  • ƙaddamar da wani abu na ilimi ba tare da wani shigarwa ba kwata-kwata
  • haɓakawa akan iOS, inda, bisa ga jita-jita, kawai aikace-aikacen da ke da haƙƙin tsara ƙira akan tashi shine injin JS (wannan gaskiya ne?)
  • nuni na mini-OS - guda-floppy, ginannen ciki, kowane nau'in firmware, da sauransu ...

Fasalolin Runtime Browser

Kamar yadda na fada a baya, QEMU tana da alaƙa da multithreading, amma mai binciken ba shi da shi. To, ma’ana, a’a... Da farko babu shi, sai WebWorkers suka bayyana – kamar yadda na fahimta, wannan shi ne multithreading dangane da isar da sako. ba tare da raba masu canji ba. A zahiri, wannan yana haifar da manyan matsaloli yayin jigilar lambar data kasance dangane da ƙirar ƙwaƙwalwar da aka raba. Sa'an nan kuma, a karkashin matsin lamba na jama'a, an kuma aiwatar da shi da sunan SharedArrayBuffers. A hankali aka gabatar da shi, sun yi bikin kaddamar da shi a cikin browsers daban-daban, sannan suka yi bikin Sabuwar Shekara, sannan kuma Meltdown ... Bayan haka sun yanke shawarar cewa m ko kuma rage lokacin auna, amma tare da taimakon memory sharing da zaren yana ƙaruwa counter, duk ɗaya ne zai yi aiki sosai daidai. Don haka mun kashe multithreading tare da haɗin gwiwar ƙwaƙwalwar ajiya. Da alama daga baya sun juya baya, amma, kamar yadda ya bayyana daga gwaji na farko, akwai rayuwa ba tare da shi ba, kuma idan haka ne, za mu yi ƙoƙari mu yi shi ba tare da dogara ga multithreading ba.

Siffa ta biyu ita ce rashin yiwuwar gyare-gyaren ƙananan matakai tare da tari: ba za ku iya ɗauka kawai ba, ajiye yanayin yanzu kuma ku canza zuwa wani sabon tare da sabon tari. Na'urar kama-da-wane ta JS ce ke sarrafa tarin kira. Zai zama alama, menene matsalar, tun da har yanzu mun yanke shawarar sarrafa tsoffin kwararar gaba ɗaya da hannu? Gaskiyar ita ce toshe I/O a cikin QEMU ana aiwatar da shi ta hanyar coroutines, kuma wannan shine inda ƙananan matakan tari zai zo da amfani. Abin farin ciki, Emscipten ya riga ya ƙunshi tsarin aiki na asynchronous, har ma biyu: Asyncify и Mai fassara. Na farko yana aiki ta hanyar kumburi mai mahimmanci a cikin lambar JavaScript da aka samar kuma ba a samun tallafi. Na biyu shine "daidaitaccen hanya" na yanzu kuma yana aiki ta hanyar tsarar bytecode ga mai fassara na asali. Yana aiki, ba shakka, a hankali, amma ba ya kumbura lambar. Gaskiya ne, dole ne a ba da gudummawar tallafi ga coroutines don wannan tsarin (an riga an rubuta coroutines don Asyncify kuma akwai aiwatar da kusan API iri ɗaya don Emterpreter, kawai kuna buƙatar haɗa su).

A halin yanzu, har yanzu ban sami nasarar raba lambar zuwa ɗaya wanda aka haɗa cikin WASM kuma an fassara shi ta amfani da Emterpreter, don haka toshe na'urorin ba su yi aiki ba tukuna (duba a cikin jerin na gaba, kamar yadda suke faɗi…). Wato, a ƙarshe ya kamata ku sami wani abu kamar wannan abu mai laushi mai ban dariya:

  • toshe I/O da aka fassara. Da kyau, shin da gaske kuna tsammanin kwaikwayi NVMe tare da aikin ɗan ƙasa? 🙂
  • babbar lambar QEMU da aka harhada a tsaye (mai fassara, sauran na'urori da aka kwaikwayi, da sauransu)
  • da kuzarin harhada lambar baƙo zuwa cikin WASM

Siffofin tushen QEMU

Kamar yadda wataƙila kun riga kuka yi tsammani, lambar don kwaikwayi gine-ginen baƙi da lambar don samar da umarnin injin runduna sun rabu a cikin QEMU. A gaskiya ma, yana da ɗan wayo:

  • akwai gine-ginen baƙi
  • ne accelerators, wato, KVM don sarrafa kayan aiki akan Linux (don baƙo da tsarin tsarin da suka dace da juna), TCG don tsara lambar JIT a ko'ina. An fara tare da QEMU 2.9, goyon baya ga ma'aunin haɓaka kayan aikin HAXM akan Windows ya bayyana (da cikakken bayani)
  • Idan ana amfani da TCG kuma ba kayan aiki na kayan aiki ba, to yana da tallafin ƙirƙirar lambar daban don kowane gine-ginen rundunar, da kuma mai fassarar duniya.
  • ... kuma a kusa da duk wannan - abubuwan da aka kwaikwayi, mai amfani da mai amfani, ƙaura, sake kunna rikodin, da sauransu.

Af, ko kun san: QEMU na iya yin koyi ba kawai gabaɗayan kwamfutar ba, har ma da mai sarrafawa don tsarin mai amfani daban a cikin kernel mai watsa shiri, wanda ake amfani da shi, misali, ta AFL fuzzer don kayan aikin binary. Wataƙila wani yana son aika wannan yanayin aiki na QEMU zuwa JS? 😉

Kamar yawancin software na kyauta na dogon lokaci, QEMU ana gina ta ta hanyar kira configure и make. Bari mu ce kun yanke shawarar ƙara wani abu: TCG baya, aiwatar da zaren, wani abu dabam. Kada ku yi gaggawar zama cikin farin ciki/ firgita (a jadada kamar yadda ya dace) a cikin tsammanin yin magana da Autoconf - a zahiri, configure QEMU's a fili an rubuta da kansa kuma ba a samo shi daga wani abu ba.

Yanar Gizo

To menene wannan abu da ake kira WebAssembly (aka WASM)? Wannan shine maye gurbin Asm.js, baya yin riya a matsayin lambar JavaScript mai aiki. Akasin haka, yana binary ne kawai kuma an inganta shi, har ma kawai rubuta lamba a ciki ba abu ne mai sauƙi ba: don haɓakawa, ana adana shi a cikin tsari. LABARIN 128.

Wataƙila kun ji game da relooping algorithm don Asm.js - wannan shine maido da umarnin kula da kwararar “high-level” (wato, idan-to, madaukai, da sauransu), wanda aka tsara injunan JS, daga ƙananan matakin LLVM IR, kusa da lambar injin da mai sarrafa ya aiwatar. A zahiri, matsakaicin wakilci na QEMU yana kusa da na biyu. Zai zama kamar a nan shi ne, bytecode, ƙarshen azaba ... Sannan akwai tubalan, idan - to - da madaukai! ...

Kuma wannan shine wani dalili da ya sa Binaryen ke da amfani: yana iya yarda da manyan matakan kusa da abin da za a adana a WASM. Amma kuma yana iya samar da lamba daga jadawali na tubalan asali da canji a tsakanin su. To, na riga na faɗi cewa yana ɓoye tsarin ajiya na WebAssembly a bayan API C/C++ dacewa.

TCG (Tiny Code Generator)

GCT ya asali baya ga mai tarawa C. Sa'an nan kuma, a fili, ba zai iya jure wa gasar tare da GCC ba, amma a ƙarshe ya sami matsayinsa a QEMU a matsayin tsarin samar da lambar don dandalin mai watsa shiri. Akwai kuma bayan TCG wanda ke haifar da wasu abstract bytecode, wanda mai fassara ke aiwatar da shi nan da nan, amma na yanke shawarar guje wa amfani da shi a wannan lokacin. Duk da haka, gaskiyar cewa a cikin QEMU ya riga ya yiwu a ba da damar sauyawa zuwa tarin tarin fuka ta hanyar aikin tcg_qemu_tb_exec, ya zama mai amfani sosai a gare ni.

Don ƙara sabon abin baya na TCG zuwa QEMU, kuna buƙatar ƙirƙirar kundin adireshi tcg/<имя архитектуры> (a cikin wannan hali, tcg/binaryen), kuma ya ƙunshi fayiloli guda biyu: tcg-target.h и tcg-target.inc.c и rubuta duk game da shi ne configure. Kuna iya sanya wasu fayiloli a wurin, amma, kamar yadda zaku iya tsammani daga sunayen waɗannan biyun, za a haɗa su duka a wani wuri: ɗaya a matsayin fayil ɗin rubutu na yau da kullun (an haɗa shi a ciki). tcg/tcg.h, kuma wancan yana cikin wasu fayiloli a cikin kundayen adireshi tcg, accel kuma ba kawai), ɗayan - kawai azaman snippet code a ciki tcg/tcg.c, amma yana da damar yin amfani da ayyukansa na tsaye.

Yanke shawarar cewa zan ɓata lokaci mai yawa akan cikakken bincike na yadda yake aiki, kawai na kwafi “skeletons” na waɗannan fayiloli guda biyu daga wani aiwatar da baya, da gaske yana nuna wannan a cikin taken lasisi.

fayil tcg-target.h ya ƙunshi saituna musamman a cikin tsari #define-s:

  • nawa rajista da abin da nisa ke akwai a kan manufa gine (muna da yawa kamar yadda muke so, da yawa kamar yadda muke so - tambaya ta fi game da abin da za a samar a cikin mafi inganci code da browser a kan "cikakken manufa" gine. ...)
  • daidaita umarnin rundunar: akan x86, har ma a cikin TCI, umarnin ba a daidaita su ba kwata-kwata, amma zan saka a cikin buffer code ba umarni kwata-kwata ba, amma masu nuni ga tsarin ɗakin karatu na Binaryen, don haka zan ce: 4 bytes
  • wane umarni na zaɓi na baya zai iya samarwa - mun haɗa da duk abin da muka samu a cikin Binaryen, bari mai haɓakawa ya karya sauran zuwa mafi sauƙi kanta.
  • Menene madaidaicin girman ma'ajin TLB da mai baya ya nema. Gaskiyar ita ce, a cikin QEMU duk abin da yake da mahimmanci: ko da yake akwai ayyuka masu taimako waɗanda ke yin kaya / kantin sayar da la'akari da MMU baƙo (a ina za mu kasance ba tare da shi ba a yanzu?), Suna adana cache na fassarar su a cikin tsari, da sarrafa wanda ya dace don saka kai tsaye cikin tubalan watsa shirye-shirye. Abin tambaya a nan shi ne, mene ne gyara a cikin wannan tsarin da aka fi sarrafa shi ta hanyar ƙaramin tsari da sauri?
  • Anan zaku iya tweak manufar rajista ɗaya ko biyu da aka tanada, ba da damar kiran tarin tarin fuka ta hanyar aiki kuma ba da zaɓin siffanta ƙanana biyu ba. inline-ayyukan kamar flush_icache_range (amma wannan ba lamarinmu bane)

fayil tcg-target.inc.c, ba shakka, yawanci ya fi girma a girman kuma yana ƙunshe da ayyuka da yawa na wajibi:

  • farawa, gami da ƙuntatawa akan waɗanne umarni zasu iya aiki akan waɗanne operands. Na kwafa a fili daga wani baya
  • aikin da ke ɗaukar umarnin bytecode ɗaya na ciki
  • Hakanan zaka iya sanya ayyukan taimako anan, kuma zaka iya amfani da ayyuka masu tsayuwa daga tcg/tcg.c

Don kaina, na zaɓi dabara mai zuwa: a cikin kalmomin farko na toshe fassarar na gaba, na rubuta alamomi huɗu: alamar farawa (wani ƙima a cikin kusanci. 0xFFFFFFFF, wanda ya ƙayyade halin yanzu na tarin fuka), mahallin mahallin, ƙirar ƙira, da lambar sihiri don gyara matsala. Da farko an sanya alamar a ciki 0xFFFFFFFF - ninda n - ƙaramin adadi mai kyau, kuma duk lokacin da aka aiwatar da shi ta hanyar fassarar yana ƙaruwa da 1. Idan ya kai 0xFFFFFFFE, tari ya faru, an ajiye module ɗin a cikin tebur ɗin aiki, an shigo da shi cikin ƙaramin “launcher”, wanda aka aiwatar da shi daga ciki. tcg_qemu_tb_exec, kuma an cire tsarin daga ƙwaƙwalwar QEMU.

Don fayyace al'adun gargajiya, "Crutch, nawa ne ke haɗuwa a cikin wannan sauti don zuciyar proger...". Duk da haka, ƙwaƙwalwar yana yabo a wani wuri. Haka kuma, QEMU ne ke sarrafa ƙwaƙwalwar ajiya! Ina da lambar da, lokacin rubuta umarni na gaba (da kyau, wato, mai nuna alama), ya share wanda hanyarsa ta kasance a wannan wuri a baya, amma wannan bai taimaka ba. A zahiri, a cikin mafi sauƙi, QEMU tana rarraba ƙwaƙwalwar ajiya a farawa kuma ta rubuta lambar da aka samar a wurin. Lokacin da buffer ya ƙare, za a jefa lambar kuma a fara rubuta na gaba a wurinsa.

Bayan nazarin lambar, na gane cewa dabarar tare da lambar sihirin ta ba ni damar kada in yi kasala a kan lalata ta hanyar 'yantar da wani abu da ba daidai ba a kan buffer mara tushe a farkon wucewar. Amma wa ke sake rubuta buffer don ƙetare aikina daga baya? Kamar yadda masu haɓaka Emscripten ke ba da shawara, lokacin da na ci karo da matsala, na tura lambar da aka samu zuwa aikace-aikacen asali, saita Mozilla Record-Replay akan shi… Gabaɗaya, a ƙarshe na fahimci abu mai sauƙi: ga kowane toshe, a struct TranslationBlock tare da bayaninsa. Yi tsammani a ina... Haka ne, kafin a toshe dama a cikin buffer. Da fahimtar haka, na yanke shawarar daina amfani da crutches (akalla wasu), kuma kawai na jefa lambar sihirin, na canza sauran kalmomin zuwa struct TranslationBlock, Ƙirƙirar jeri guda ɗaya da aka haɗe wanda za'a iya wucewa da sauri lokacin da aka sake saita cache na fassarar, kuma ya 'yantar da ƙwaƙwalwar ajiya.

Wasu ƙugiya sun kasance: alal misali, alamomi masu alama a cikin buffer code - wasu daga cikinsu suna da sauƙi BinaryenExpressionRef, wato, suna duban maganganun da ake buƙatar sakawa a layi a cikin tubalin da aka samar, wani ɓangare shine yanayin sauyawa tsakanin BBs, sashi shine inda za a je. Da kyau, an riga an shirya tubalan don Relooper waɗanda ke buƙatar haɗa su gwargwadon sharuɗɗan. Don bambance su, ana amfani da zato cewa duk an daidaita su da aƙalla bytes huɗu, don haka zaku iya amfani da mafi ƙarancin ragi biyu don alamar, kawai kuna buƙatar tunawa don cire shi idan ya cancanta. Af, an riga an yi amfani da irin waɗannan alamun a cikin QEMU don nuna dalilin fita daga madauki na TCG.

Amfani da Binaryen

Modules a cikin Gidan Yanar Gizo yana ƙunshe da ayyuka, kowannensu yana ɗauke da jiki, wanda shine magana. Kalmomi sune ayyukan unary da binary, tubalan da suka ƙunshi jerin wasu maganganu, kwararar sarrafawa, da sauransu. Kamar yadda na fada a baya, ana shirya kwararar sarrafawa a nan daidai kamar manyan rassan rassan, madaukai, kiran aiki, da sauransu. Ba a ba da hujja ga ayyuka akan tari ba, amma a sarari, kamar a cikin JS. Hakanan akwai masu canji na duniya, amma ban yi amfani da su ba, don haka ba zan gaya muku game da su ba.

Ayyuka kuma suna da masu canji na gida, masu ƙidaya daga sifili, na nau'in: int32 / int64 / float / biyu. A wannan yanayin, na farko n masu canji na gida sune muhawarar da aka wuce zuwa aikin. Lura cewa duk da cewa duk abin da ke nan ba ƙaƙƙarfan matakin ƙasa ba ne dangane da kwararar sarrafawa, lamba har yanzu ba sa ɗaukar sifa "sa hannu/marasa hannu": yadda lambar ke aiki ya dogara da lambar aiki.

Gabaɗaya magana, Binaryen yana bayarwa sauki C-API: ka ƙirƙiri module, a cikinsa ƙirƙirar maganganu - unary, binary, tubalan daga wasu maganganu, sarrafawar gudana, da dai sauransu. Sa'an nan kuma ka ƙirƙiri aiki tare da magana a matsayin jikinsa. Idan ku, kamar ni, kuna da jadawali mai ƙaranci, ɓangaren relooper zai taimake ku. Kamar yadda na fahimta, yana yiwuwa a yi amfani da babban matakin sarrafa tsarin aiwatar da aiwatarwa a cikin toshe, idan dai bai wuce iyakokin toshe ba - wato, yana yiwuwa a yi saurin ciki / sannu a hankali. hanyar reshe a cikin ginanniyar lambar sarrafa cache na TLB, amma ba don tsoma baki tare da kwararar sarrafawar "waje". Lokacin da ka 'yantar da relooper, tubalan nasa suna 'yantar da su, lokacin da ka 'yantar da module, maganganun, ayyuka, da sauransu. fagen fama.

Koyaya, idan kuna son fassara lambar akan tashi ba tare da ƙirƙira da ba dole ba da share misali na fassarar, yana iya yin ma'ana don sanya wannan ma'ana a cikin fayil ɗin C ++, kuma daga can kai tsaye sarrafa duk C ++ API na ɗakin karatu, ta ƙetare shirye- sanya wrappers.

Don haka don samar da lambar da kuke buƙata

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

... idan na manta wani abu, yi hakuri, wannan shine kawai don wakiltar ma'auni, kuma cikakkun bayanai suna cikin takardun.

Kuma yanzu crack-fex-pex ya fara, wani abu kamar haka:

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

Don haɗa ko ta yaya duniyoyin QEMU da JS kuma a lokaci guda samun damar ayyukan da aka haɗa cikin sauri, an ƙirƙiri jeri (tebur na ayyuka don shigo da shi cikin ƙaddamarwa), kuma an sanya ayyukan da aka ƙirƙira a wurin. Don ƙididdige fihirisar da sauri, an fara amfani da ma'aunin toshe fassarar kalmar sifili kamar yadda yake, amma sai fihirisar da aka ƙididdige ta amfani da wannan dabara ta fara shiga cikin filin cikin sauƙi. struct TranslationBlock.

Af, demo (a halin yanzu tare da lasisi mai rauni) Yana aiki lafiya kawai a Firefox. Masu haɓaka Chrome sun kasance ko ta yaya ba a shirye ba don gaskiyar cewa wani zai so ya ƙirƙiri fiye da misalai dubu na samfuran WebAssembly, don haka kawai sun ware gigabyte na sararin adireshi mai kama-da-wane ga kowane ...

Shi ke nan a yanzu. Wataƙila za a sami wani labarin idan kowa yana sha'awar. Wato, akwai saura aƙalla kawai sa block na'urorin aiki. Hakanan yana iya yin ma'ana don sanya haɗar samfuran WebAssembly asynchronous, kamar yadda aka saba a duniyar JS, tunda har yanzu akwai mai fassarar da zai iya yin duk wannan har sai an shirya tsarin na asali.

Daga karshe kacici-kacici: kun tattara binary akan tsarin gine-ginen 32-bit, amma lambar, ta hanyar ayyukan ƙwaƙwalwar ajiya, hawa daga Binaryen, wani wuri akan tari, ko wani wuri a cikin babban 2 GB na sararin adireshi 32-bit. Matsalar ita ce daga ra'ayi na Binaryen wannan yana samun isa ga babban adireshin sakamakon. Yadda za a kewaye da wannan?

A hanyar admin

Ban gama gwada wannan ba, amma tunanina na farko shine "Idan na shigar da Linux 32-bit fa?" Sa'an nan kuma ɓangaren sama na sararin adireshi zai mamaye kernel. Tambaya kawai ita ce nawa za a shagaltar da su: 1 ko 2 Gb.

A hanyar mai shirye-shirye (zaɓi ga masu aiki)

Bari mu busa kumfa a saman sararin adireshin. Ni kaina ban fahimci dalilin da yasa yake aiki ba - akwai riga dole ne a sami tari. Amma "mu masu aiki ne: komai yana aiki a gare mu, amma babu wanda ya san dalilin da ya sa..."

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

Gaskiya ne cewa bai dace da Valgrind ba, amma, an yi sa'a, Valgrind da kanta tana tura kowa da kowa daga wurin sosai :)

Watakila wani zai yi karin bayani kan yadda wannan lambar tawa ke aiki...

source: www.habr.com

Add a comment