QEMU.js: karon seryoso na ug naay WASM

Sa usa ka panahon nakahukom ko nga maglingaw-lingaw pamatud-an ang pagkabalikbalik sa proseso ug pagkat-on unsaon paghimo og JavaScript (mas tukma, Asm.js) gikan sa machine code. Gipili ang QEMU alang sa eksperimento, ug pipila ka panahon sa ulahi usa ka artikulo ang gisulat sa Habr. Sa mga komento gitambagan ako nga i-remake ang proyekto sa WebAssembly, ug bisan ang pag-undang sa akong kaugalingon hapit na mahuman Sa usa ka paagi dili ko gusto ang proyekto ... Ang trabaho nagpadayon, apan hinay kaayo, ug karon, bag-o lang sa kana nga artikulo nagpakita usa ka komento sa topiko nga “Busa sa unsang paagi natapos ang tanan?” Agig tubag sa akong detalyado nga tubag, akong nadungog ang "Kini morag usa ka artikulo." Aw, kung mahimo nimo, adunay usa ka artikulo. Tingali adunay makakita niini nga mapuslanon. Gikan niini ang magbabasa makakat-on sa pipila ka mga kamatuoran mahitungod sa disenyo sa QEMU code generation backends, ingon man sa unsa nga paagi sa pagsulat sa usa ka Just-in-Time compiler alang sa usa ka web application.

buluhaton

Tungod kay nahibal-an na nako kung giunsa "sa usa ka paagi" i-port ang QEMU sa JavaScript, niining higayona nakahukom nga buhaton kini nga maalamon ug dili balikon ang daan nga mga sayup.

Sayop numero uno: sanga gikan sa pagpagawas sa punto

Ang una nakong sayop mao ang pag-fork sa akong bersyon gikan sa upstream nga bersyon 2.4.1. Unya ingon og usa ka maayong ideya alang kanako: kung adunay pagpagawas sa punto, nan kini tingali mas lig-on kaysa yano nga 2.4, ug labi pa ang sanga. master. Ug tungod kay nagplano ako nga magdugang usa ka patas nga kantidad sa akong kaugalingon nga mga bug, wala gyud nako kinahanglan ang bisan kinsa. Mao na siguro ang nahitabo. Apan ania ang butang: Ang QEMU wala mohunong, ug sa usa ka punto gipahibalo pa nila ang pag-optimize sa nahimo nga code sa porsyento nga 10. "Oo, karon mag-freeze na ako," naghunahuna ko ug naguba. Dinhi kinahanglan namong maghimo ug digression: tungod sa single-threaded nga kinaiya sa QEMU.js ug sa kamatuoran nga ang orihinal nga QEMU wala magpasabot sa pagkawala sa multi-threading (nga mao, ang abilidad sa dungan nga pag-operate sa daghang wala'y kalabutan nga code paths, ug dili lang "gamiton ang tanan nga mga kernel") kritikal alang niini, ang mga nag-unang gimbuhaton sa mga hilo nga kinahanglan nako nga "i-turn out" aron makatawag gikan sa gawas. Naghimo kini og pipila ka natural nga mga problema sa panahon sa paghiusa. Apan, ang kamatuoran nga ang pipila sa mga kausaban gikan sa sanga master, diin ako misulay sa paghiusa sa akong code, mga cherry usab nga gipili sa punto release (ug busa sa akong sanga) usab tingali dili makadugang kasayon.

Sa kinatibuk-an, nakahukom ko nga makatarunganon gihapon nga ilabay ang prototype, i-disassemble kini alang sa mga bahin ug magtukod og bag-ong bersyon gikan sa scratch base sa usa ka butang nga mas presko ug karon gikan sa master.

Sayop numero duha: TLP nga pamaagi

Sa esensya, dili kini usa ka sayup, sa kinatibuk-an, kini usa lamang ka bahin sa paghimo sa usa ka proyekto sa mga kondisyon nga hingpit nga dili pagsinabtanay sa "diin ug unsaon paglihok?" ug sa kinatibuk-an "makaabut ba kita didto?" Sa niini nga mga kahimtang clumsy nga programming usa ka makatarunganon nga kapilian, apan, natural, dili ko gusto nga balikon kini nga wala kinahanglana. Niining higayona gusto nako nga buhaton kini sa maalamon nga paagi: atomic commits, conscious code changes (ug dili "paghugpong sa random nga mga karakter hangtud nga kini mag-compile (uban ang mga pasidaan)", ingon sa gisulti kaniadto ni Linus Torvalds mahitungod sa usa ka tawo, sumala sa Wikiquote), ug uban pa.

Ikatulo nga sayop: ang pagsulod sa tubig nga wala nahibal-an ang ford

Wala pa nako kini hingpit nga nawala, apan karon nakahukom ko nga dili sundon ang dalan nga labing gamay nga pagsukol, ug buhaton kini "ingon usa ka hamtong," nga mao, isulat ang akong TCG backend gikan sa wala, aron dili nga kinahanglan isulti sa ulahi, "Oo, kini siyempre, hinay-hinay, apan dili nako makontrol ang tanan - ingon niana ang pagsulat sa TCI ..." Dugang pa, kini sa sinugdan ingon usa ka klaro nga solusyon, sukad Naghimo ko og binary code. Sama sa giingon nila, "Nagtipon si Ghentу, apan dili kana": ang code, siyempre, binary, apan ang kontrol dili mahimo nga ibalhin lang niini - kinahanglan nga tin-aw nga iduso kini sa browser alang sa pagtipon, nga moresulta sa usa ka butang gikan sa kalibutan sa JS, nga kinahanglan pa maluwas sa usa ka dapit. Bisan pa, sa normal nga mga arkitektura sa RISC, sa akong nasabtan, usa ka tipikal nga sitwasyon ang kinahanglan nga klaro nga i-reset ang cache sa panudlo alang sa gibag-o nga code - kung dili kini ang kinahanglan naton, nan, sa bisan unsang kaso, hapit na. Dugang pa, gikan sa akong katapusang pagsulay, nahibal-an nako nga ang kontrol ingon og dili ibalhin sa tunga-tunga sa block sa paghubad, mao nga dili na kinahanglan ang bytecode nga gihubad gikan sa bisan unsang offset, ug mahimo ra naton kini nga mabuhat gikan sa function sa TB. .

Miabot sila ug nagsipa

Bisan kung gisugdan nako ang pagsulat pag-usab sa code kaniadtong Hulyo, usa ka magic kick ang wala mamatikdi: kasagaran ang mga sulat gikan sa GitHub moabut ingon nga mga pahibalo bahin sa mga tubag sa Mga Isyu ug mga hangyo sa Pull, apan dinhi, kalit mention sa thread Binaryen isip backend sa qemu sa konteksto, "Gibuhat niya ang ingon niana, tingali adunay isulti siya." Naghisgot kami bahin sa paggamit sa may kalabotan nga librarya ni Emscripten Binaryen sa paghimo sa WASM JIT. Aw, giingon ko nga ikaw adunay usa ka Apache 2.0 nga lisensya didto, ug ang QEMU sa kinatibuk-an gipang-apod-apod ubos sa GPLv2, ug sila dili kaayo compatible. Sa kalit kini nahimo nga usa ka lisensya ayoha kini bisan unsaon (Wala ko kahibalo: tingali usbon kini, tingali dual licensing, tingali lain pa...). Kini, siyempre, nakapalipay kanako, tungod kay niadtong panahona ako nagtan-aw na pag-ayo binary nga pormat WebAssembly, ug ako naguol ug dili masabtan. Adunay usab usa ka librarya nga molamoy sa mga batakang bloke nga adunay transition graph, maghimo sa bytecode, ug gani modagan kini sa tighubad mismo, kung gikinahanglan.

Unya naa pay daghan usa ka sulat sa QEMU mailing list, apan kini labaw pa mahitungod sa pangutana, "Kinsa pa man ang nagkinahanglan niini?" Ug mao kini kalit, kini nahimo nga gikinahanglan. Sa labing gamay, mahimo nimong i-scrape ang ingon nga mga posibilidad sa paggamit kung kini molihok nga labi ka dali o dili kaayo:

  • paglansad sa usa ka butang nga pang-edukasyon nga wala’y bisan unsang pag-install
  • virtualization sa iOS, diin, sumala sa mga hungihong, ang bugtong aplikasyon nga adunay katungod sa paghimo sa code sa langaw mao ang usa ka makina sa JS (tinuod ba kini?)
  • demonstrasyon sa mini-OS - single-floppy, built-in, tanang matang sa firmware, etc...

Mga Feature sa Browser Runtime

Sama sa giingon ko na, ang QEMU nahigot sa multithreading, apan ang browser wala niini. Aw, sa ato pa, dili... Sa sinugdan wala gyud kini, unya mitungha ang WebWorkers - sa akong nasabtan, kini multithreading base sa pagpasa sa mensahe walay shared variables. Siyempre, kini nagmugna og mahinungdanong mga problema sa pag-port sa kasamtangan nga code base sa shared memory model. Unya, ubos sa pressure sa publiko, gipatuman usab ubos sa ngalan SharedArrayBuffers. Anam-anam kini nga gipaila, gisaulog nila ang paglansad niini sa lainlaing mga browser, dayon gisaulog nila ang Bag-ong Tuig, ug dayon ang Meltdown ... Human niini nakahinapos sila nga coarse o coarse ang pagsukod sa oras, apan sa tabang sa gipaambit nga panumduman ug usa ka thread incrementing sa counter, parehas ra tanan kini molihok nga tukma kaayo. Mao nga gi-disable namon ang multithreading nga adunay gipaambit nga memorya. Morag gibalik nila kini sa ulahi, apan, ingon nga kini nahimong tin-aw gikan sa unang eksperimento, adunay kinabuhi nga wala niini, ug kung mao, atong sulayan nga buhaton kini nga dili magsalig sa multithreading.

Ang ikaduha nga bahin mao ang imposibilidad sa ubos nga lebel nga pagmaniobra sa stack: dili nimo mahimo nga kuhaon, i-save ang karon nga konteksto ug ibalhin sa usa ka bag-o nga adunay bag-ong stack. Ang call stack gidumala sa JS virtual machine. Morag, unsa ang problema, tungod kay nakahukom pa kami nga pagdumala sa una nga mga agos sa hingpit nga mano-mano? Ang tinuod mao nga ang block I/O sa QEMU gipatuman pinaagi sa mga coroutine, ug dinhi magamit ang ubos nga lebel nga pagmaniobra sa stack. Maayo na lang, ang Emscipten aduna nay mekanismo alang sa asynchronous nga mga operasyon, bisan duha: Asyncify и Emterpreter. Ang una naglihok pinaagi sa hinungdanon nga pagbuto sa nahimo nga JavaScript code ug wala na gisuportahan. Ang ikaduha mao ang kasamtangan nga "husto nga paagi" ug nagtrabaho pinaagi sa bytecode nga henerasyon alang sa lumad nga tighubad. Nagtrabaho kini, siyempre, hinay-hinay, apan dili kini mabuak ang code. Tinuod, ang suporta alang sa mga coroutine alang niini nga mekanismo kinahanglan nga mag-amot nga independente (adunay na mga coroutine nga gisulat para sa Asyncify ug adunay usa ka pagpatuman sa gibana-bana nga parehas nga API alang sa Emterpreter, kinahanglan nimo nga ikonektar sila).

Sa pagkakaron, wala pa ko makahimo sa pagbahin sa code ngadto sa usa nga gihugpong sa WASM ug gihubad gamit ang Emterpreter, mao nga ang mga block device wala pa molihok (tan-awa sa sunod nga serye, sumala sa ilang giingon ...). Kana mao, sa katapusan kinahanglan nimo nga makakuha usa ka butang nga sama niining kataw-anan nga layered nga butang:

  • gihubad nga block I/O. Aw, gidahom ba nimo nga gisunod ang NVMe nga adunay lumad nga pasundayag? 🙂
  • statically compiled main QEMU code (translator, ubang gisundog nga mga device, etc.)
  • dinamikong gihugpong guest code ngadto sa WASM

Mga bahin sa mga tinubdan sa QEMU

Sama sa imong natag-an na, ang code alang sa pagsunod sa mga arkitektura sa bisita ug ang code alang sa paghimo og mga panudlo sa host machine gibulag sa QEMU. Sa tinuud, kini labi ka labi ka labi:

  • adunay mga bisita nga arkitektura
  • mao mga accelerator, nga mao, KVM alang sa hardware virtualization sa Linux (alang sa mga bisita ug host nga mga sistema compatible sa usag usa), TCG alang sa JIT code generation bisan asa. Sugod sa QEMU 2.9, suporta para sa HAXM hardware virtualization standard sa Windows nagpakita (ang mga detalye)
  • kung ang TCG gigamit ug dili ang virtualization sa hardware, nan kini adunay bulag nga suporta sa henerasyon sa code alang sa matag arkitektura sa host, ingon man alang sa unibersal nga tighubad
  • ... ug sa palibot niining tanan - gisundog nga mga peripheral, user interface, paglalin, record-replay, ug uban pa.

By the way, nahibal-an ba nimo: Ang QEMU mahimong mosundog dili lamang sa tibuok kompyuter, kondili usab sa processor alang sa usa ka separado nga proseso sa user sa host kernel, nga gigamit, pananglitan, sa AFL fuzzer alang sa binary instrumentation. Tingali adunay gusto nga i-port kini nga mode sa operasyon sa QEMU sa JS? 😉

Sama sa kadaghanan sa dugay na nga libre nga software, ang QEMU gitukod pinaagi sa tawag configure и make. Ingnon ta nga nakahukom ka nga magdugang usa ka butang: usa ka backend sa TCG, pagpatuman sa thread, uban pa. Ayaw pagdali nga malipay / mahadlok (underline kung angay) sa posibilidad nga makigkomunikar sa Autoconf - sa tinuud, configure Ang QEMU dayag nga gisulat sa kaugalingon ug wala gimugna gikan sa bisan unsang butang.

WebAssembly

Busa unsa ang gitawag nga WebAssembly (aka WASM)? Kini usa ka puli sa Asm.js, dili na magpakaaron-ingnon nga balido nga JavaScript code. Sa kasukwahi, kini lunsay binary ug na-optimize, ug bisan ang pagsulat lamang sa usa ka integer niini dili kaayo yano: alang sa pagkakomplikado, kini gitipigan sa format LEB128.

Tingali nakadungog na ka bahin sa relooping algorithm alang sa Asm.js - kini ang pagpahiuli sa "taas nga lebel" nga mga panudlo sa pagkontrol sa dagan (nga mao, kung-unsa-sa pa, mga galong, ug uban pa), diin ang mga makina sa JS gidisenyo, gikan sa ang ubos nga lebel nga LLVM IR, mas duol sa machine code nga gipatuman sa processor. Natural, ang intermediate nga representasyon sa QEMU mas duol sa ikaduha. Morag ania na, bytecode, ang katapusan sa pagsakit... Ug unya adunay mga bloke, kung-on-sa-lain pa ug mga galong!..

Ug kini usa pa ka hinungdan ngano nga ang Binaryen mapuslanon: kini natural nga makadawat sa taas nga lebel nga mga bloke nga duol sa kung unsa ang tipigan sa WASM. Apan makahimo usab kini og code gikan sa usa ka graph sa mga batakang bloke ug mga transisyon tali kanila. Aw, giingon na nako nga gitago niini ang format sa pagtipig sa WebAssembly luyo sa kombenyente nga C/C++ API.

TCG (Tiny Code Generator)

GTC sa orihinal backend alang sa C compiler. Unya, dayag, kini dili makasugakod sa kompetisyon uban sa GCC, apan sa katapusan kini nakakaplag sa iyang dapit sa QEMU ingon sa usa ka code generation mekanismo alang sa host plataporma. Adunay usab usa ka backend sa TCG nga nagmugna og pipila ka abstract bytecode, nga gipatuman dayon sa tighubad, apan nakahukom ko nga likayan ang paggamit niini niining panahona. Apan, ang kamatuoran nga sa QEMU posible na nga makahimo sa transisyon ngadto sa namugna nga TB pinaagi sa function tcg_qemu_tb_exec, kini nahimong mapuslanon kaayo alang kanako.

Para makadugang ug bag-ong TCG backend sa QEMU, kinahanglan ka maghimo ug subdirectory tcg/<имя архитектуры> (sa kini nga kaso, tcg/binaryen), ug kini adunay duha ka mga file: tcg-target.h и tcg-target.inc.c и magparehistro kini mahitungod sa tanan configure. Mahimo nimong ibutang ang ubang mga file didto, apan, ingon nga imong matag-an gikan sa mga ngalan niining duha, silang duha iapil sa usa ka lugar: usa ingon usa ka regular nga file sa header (kini gilakip sa tcg/tcg.h, ug kanang usa naa na sa ubang mga file sa mga direktoryo tcg, accel ug dili lang), ang lain - isip usa ka code snippet in tcg/tcg.c, apan kini adunay access sa iyang mga static function.

Sa pagdesisyon nga mogugol ako ug daghang oras sa mga detalyado nga imbestigasyon kung giunsa kini molihok, gikopya ra nako ang "mga kalabera" niining duha nga mga file gikan sa lain nga pagpatuman sa backend, matinud-anon nga nagpakita niini sa header sa lisensya.

file tcg-target.h naglangkob nag-una nga mga setting sa porma #define-s:

  • pila ka mga rehistro ug unsa ka lapad ang naa sa target nga arkitektura (adunay kami kutob sa among gusto, kutob sa among gusto - ang pangutana labi pa kung unsa ang mahimo nga labi ka episyente nga code sa browser sa "hingpit nga target" nga arkitektura ...)
  • pag-align sa mga instruksyon sa host: sa x86, ug bisan sa TCI, ang mga instruksyon wala gayud nahiuyon, apan akong ibutang sa code buffer dili mga instruksiyon, apan mga punto sa Binaryen library structures, mao nga ako moingon: 4 bytes
  • unsa nga opsyonal nga mga instruksyon nga mahimo sa backend - among gilakip ang tanan nga among makit-an sa Binaryen, tugoti ang accelerator nga magbungkag sa uban ngadto sa mas simple nga mga butang.
  • Unsa ang gibanabana nga gidak-on sa TLB cache nga gihangyo sa backend. Ang tinuod mao nga sa QEMU ang tanan seryoso: bisan kung adunay mga function sa katabang nga nagpahigayon sa pagkarga / tindahan nga gikonsiderar ang bisita nga MMU (diin kita kung wala kini karon?), Gitipigan nila ang ilang cache sa paghubad sa porma sa usa ka istruktura, ang Ang pagproseso niini sayon ​​​​nga i-embed direkta sa mga bloke sa sibya. Ang pangutana mao, unsa nga offset sa kini nga istruktura ang labing episyente nga giproseso sa usa ka gamay ug paspas nga han-ay sa mga mando?
  • dinhi mahimo nimong i-tweak ang katuyoan sa usa o duha nga gireserba nga mga rehistro, makahimo sa pagtawag sa TB pinaagi sa usa ka function ug opsyonal nga ihulagway ang usa ka magtiayon nga gagmay inline- mga function sama sa flush_icache_range (apan dili kini ang among kaso)

file tcg-target.inc.c, siyempre, kasagaran mas dako ang gidak-on ug adunay daghang mandatory nga mga gimbuhaton:

  • inisyalisasyon, lakip ang mga pagdili kung asa nga mga instruksyon ang mahimong molihok kung asa nga mga operand. Klarong gikopya nako gikan sa laing backend
  • function nga nagkinahanglan og usa ka internal nga bytecode nga instruksyon
  • Mahimo usab nimo ibutang ang mga auxiliary function dinhi, ug mahimo usab nimo gamiton ang mga static function gikan sa tcg/tcg.c

Alang sa akong kaugalingon, gipili nako ang mosunod nga estratehiya: sa unang mga pulong sa sunod nga block sa paghubad, gisulat nako ang upat ka mga punto: usa ka marka sa pagsugod (usa ka piho nga kantidad sa palibot 0xFFFFFFFF, nga nagtino sa kasamtangan nga kahimtang sa TB), konteksto, namugna nga module, ug magic number para sa pag-debug. Sa sinugdan ang marka gibutang sa 0xFFFFFFFF - ndiin n - usa ka gamay nga positibo nga numero, ug sa matag higayon nga kini gipatuman pinaagi sa tighubad kini nagdugang sa 1. Sa diha nga kini miabut 0xFFFFFFFE, ang paghugpong nahitabo, ang module na-save sa function table, gi-import ngadto sa usa ka gamay nga "launcher", diin ang pagpatay gikan sa tcg_qemu_tb_exec, ug ang module gikuha gikan sa QEMU memory.

Sa paraphrase sa classics, "Crutch, unsa ka daghan ang intertwined niini nga tingog alang sa proger sa kasingkasing ...". Bisan pa, ang panumduman nagtulo sa usa ka lugar. Dugang pa, kini memorya nga gidumala sa QEMU! Naa koy code nga, sa pagsulat sa sunod nga instruksyon (maayo, sa ato pa, usa ka pointer), gitangtang ang usa kansang link naa sa kini nga lugar sa sayo pa, apan wala kini makatabang. Sa tinuud, sa pinakasimple nga kaso, ang QEMU naggahin sa memorya sa pagsugod ug gisulat ang nahimo nga code didto. Kung mahurot na ang buffer, ilabay ang code ug ang sunod magsugod nga isulat sa lugar niini.

Human sa pagtuon sa code, akong naamgohan nga ang lansis nga adunay magic number nagtugot kanako nga dili mapakyas sa heap destruction pinaagi sa pagpalingkawas sa usa ka butang nga sayup sa usa ka uninitialized buffer sa unang pass. Apan kinsa ang nag-rewrite sa buffer aron malaktawan ang akong function sa ulahi? Ingon sa gitambag sa mga developers sa Emscripten, sa dihang nakasugat ko og problema, akong gi-port ang resulta nga code balik sa lumad nga aplikasyon, gibutang ang Mozilla Record-Replay niini... Sa kinatibuk-an, sa katapusan nakaamgo ko og usa ka yano nga butang: alang sa matag block, a struct TranslationBlock uban sa paghulagway niini. Tag-ana kung asa... Husto kana, sa wala pa ang block sa buffer. Nakaamgo niini, nakahukom ko nga mohunong sa paggamit sa crutches (labing menos pipila), ug yanong gilabay ang magic nga numero, ug gibalhin ang nahabilin nga mga pulong ngadto sa struct TranslationBlock, paghimo og usa ka single linked list nga daling maagian kung ang translation cache i-reset, ug libre ang memorya.

Ang ubang mga crutches nagpabilin: pananglitan, gimarkahan nga mga pointer sa code buffer - ang uban niini yano ra BinaryenExpressionRef, nga mao, ilang gitan-aw ang mga ekspresyon nga kinahanglan nga linearly ibutang sa namugna nga batakang bloke, ang bahin mao ang kondisyon alang sa transisyon tali sa mga BB, bahin kung asa moadto. Aw, aduna nay giandam nga mga bloke para sa Relooper nga kinahanglang konektado sumala sa mga kondisyon. Aron mailhan sila, gigamit ang pangagpas nga silang tanan gipahiangay sa labing menos upat ka byte, aron luwas nga magamit nimo ang labing gamay nga hinungdanon nga duha ka piraso alang sa label, kinahanglan nimo nga hinumdoman nga tangtangon kini kung kinahanglan. Pinaagi sa dalan, ang ingon nga mga label gigamit na sa QEMU aron ipakita ang hinungdan sa paggawas sa TCG loop.

Paggamit sa Binaryen

Ang mga module sa WebAssembly adunay mga function, nga ang matag usa adunay usa ka lawas, nga usa ka ekspresyon. Ang mga ekspresyon mao ang unary ug binary nga mga operasyon, mga bloke nga naglangkob sa mga lista sa ubang mga ekspresyon, pagkontrol sa dagan, ug uban pa. Sama sa giingon ko na, ang pag-agos sa pagkontrol dinhi gi-organisar nga tukma ingon mga taas nga lebel nga mga sanga, mga galong, mga tawag sa function, ug uban pa. Ang mga argumento sa mga gimbuhaton wala gipasa sa stack, apan klaro, sama sa JS. Adunay usab mga global variable, apan wala nako kini gigamit, mao nga dili nako isulti kanimo ang bahin niini.

Ang mga gimbuhaton usab adunay lokal nga mga variable, ginumero gikan sa zero, sa tipo: int32 / int64 / float / doble. Sa kini nga kaso, ang una nga n lokal nga mga variable mao ang mga argumento nga gipasa sa function. Palihug timan-i nga bisan kung ang tanan dinhi dili hingpit nga ubos nga lebel sa mga termino sa kontrol nga dagan, ang mga integer wala gihapon nagdala sa "gipirmahan / wala'y pirma" nga hiyas: kung giunsa ang paglihok sa numero nagdepende sa code sa operasyon.

Sa kinatibuk-an nga pagsulti, ang Binaryen naghatag simple nga C-API: maghimo ka ug module, diha kaniya paghimo mga ekspresyon - unary, binary, mga bloke gikan sa ubang mga ekspresyon, pagkontrol sa dagan, ug uban pa. Unya maghimo ka usa ka function nga adunay usa ka ekspresyon ingon nga lawas niini. Kung ikaw, sama kanako, adunay ubos nga lebel sa transisyon graph, ang relooper component makatabang kanimo. Sa akong nasabtan, posible nga gamiton ang taas nga lebel nga kontrol sa dagan sa pagpatuman sa usa ka bloke, basta dili kini molapas sa mga utlanan sa block - nga mao, posible nga maghimo sa internal nga paspas nga agianan / hinay. path branching sulod sa built-in TLB cache processing code, apan dili makabalda sa “external” control flow . Kung imong gibuhian ang usa ka relooper, ang mga bloke niini gipagawas; kung imong gipagawas ang usa ka module, ang mga ekspresyon, mga gimbuhaton, ug uban pa nga gigahin niini mawala. arena.

Bisan pa, kung gusto nimo nga hubaron ang code sa langaw nga wala kinahanglana nga paghimo ug pagtangtang sa usa ka pananglitan sa tighubad, mahimo’g makatarunganon nga ibutang kini nga lohika sa usa ka C++ nga file, ug gikan didto direkta nga pagdumala sa tibuuk nga C++ API sa librarya, nga naglikay sa andam- gihimo nga mga wrapper.

Busa aron makamugna ang code nga imong gikinahanglan

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

... kung nakalimtan nako ang bisan unsang butang, pasayloa, kini para lang magrepresentar sa sukod, ug ang mga detalye naa sa dokumentasyon.

Ug karon nagsugod ang crack-fex-pex, sama niini:

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

Aron sa usa ka paagi makonektar ang mga kalibutan sa QEMU ug JS ug sa samang higayon dali nga ma-access ang mga nahipos nga mga gimbuhaton, usa ka array ang gihimo (usa ka talaan sa mga gimbuhaton alang sa pag-import sa launcher), ug ang mga nahimo nga mga gimbuhaton gibutang didto. Aron dali nga makalkulo ang indeks, ang indeks sa bloke sa paghubad sa pulong nga zero sa sinugdan gigamit ingon niini, apan pagkahuman ang indeks nga gikalkula gamit kini nga pormula nagsugod nga mohaum lang sa natad sa struct TranslationBlock.

Hinuon, demo (karon adunay dili maayo nga lisensya) maayo ra ang pagtrabaho sa Firefox. Ang mga nag-develop sa Chrome kaniadto dili pa andam sa kamatuoran nga adunay usa nga gusto nga maghimo labaw pa sa usa ka libo nga mga higayon sa mga module sa WebAssembly, mao nga naggahin sila usa ka gigabyte nga virtual address space alang sa matag ...

Kana lang sa pagkakaron. Tingali adunay lain nga artikulo kung adunay interesado. Nga mao, adunay nagpabilin sa labing menos lamang paghimo sa mga block device nga molihok. Mahimo usab nga makatarunganon ang paghimo sa paghugpong sa mga module sa WebAssembly nga asynchronous, sama sa naandan sa JS nga kalibutan, tungod kay adunay usa ka tighubad nga makahimo sa tanan niini hangtod nga ang lumad nga module andam na.

Sa katapusan usa ka tigmo: imong gihugpong ang usa ka binary sa usa ka 32-bit nga arkitektura, apan ang code, pinaagi sa mga operasyon sa memorya, mosaka gikan sa Binaryen, sa usa ka dapit sa stack, o sa laing dapit sa ibabaw nga 2 GB sa 32-bit nga address space. Ang problema mao nga gikan sa panglantaw ni Binaryen kini nag-access sa dako kaayo nga resulta nga adres. Unsaon paglibot niini?

Sa paagi ni admin

Wala nako nahuman ang pagsulay niini, apan ang una nakong gihunahuna mao ang "Unsa kaha kung akong gi-install ang 32-bit Linux?" Dayon ang ibabaw nga bahin sa address space paga-okupar sa kernel. Ang pangutana lang kung pila ang ma-okupar: 1 o 2 Gb.

Sa paagi sa programmer (opsyon para sa mga practitioner)

Atong huypon ang usa ka bula sa ibabaw sa address space. Ako sa akong kaugalingon wala makasabut ngano nga kini molihok - didto na kinahanglan nga adunay usa ka stack. Apan "kami mga practitioner: ang tanan nagtrabaho alang kanamo, apan walay usa nga nahibal-an kung ngano ..."

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

... tinuod nga dili kini katugma sa Valgrind, apan, maayo na lang, ang Valgrind mismo epektibo nga nagduso sa tanan gikan didto :)

Tingali adunay maghatag usa ka labi ka maayo nga pagpasabut kung giunsa kini nga kodigo molihok ...

Source: www.habr.com

Idugang sa usa ka comment