JIT ပံ့ပိုးမှုဖြင့် Qemu.js- သင်သည် mince ကို နောက်ပြန်လှည့်နိုင်သည်။

လွန်ခဲ့သောနှစ်အနည်းငယ်က Fabrice Bellard jslinux မှရေးသားခဲ့သည် JavaScript ဖြင့်ရေးသားထားသော PC emulator တစ်ခုဖြစ်သည်။ အဲဒီနောက်မှာ အနည်းဆုံးတော့ ပိုပါတယ်။ x86 အတု. ဒါပေမယ့် ကျွန်တော်သိသလောက်တော့ သူတို့အားလုံးဟာ တူညီတဲ့ Fabrice Bellard က စောစောကရေးခဲ့တဲ့ Qemu က စကားပြန်တွေဖြစ်ပြီး၊ ကိုယ့်ကိုယ်ကိုယ် လေးစားတဲ့ ခေတ်မီ emulator က JIT compilation of guest code ကို host system code အဖြစ် အသုံးပြုပါတယ်။ ဘရောက်ဆာများဖြေရှင်းပေးသည့်အရာနှင့်စပ်လျဉ်းသည့်ဆန့်ကျင်ဘက်အလုပ်တစ်ခုကိုအကောင်အထည်ဖော်ရန်အချိန်တန်ပြီဖြစ်သည်- JIT မှစက်ကုဒ်ကို JavaScript သို့ JIT တွင်စုစည်းထားသောကြောင့် Qemu ကိုပို့ရန်အလွန်ယုတ္တိရှိပုံပေါက်သည်။ Qemu၊ အဘယ်ကြောင့်ဆိုသော် ရိုးရှင်းပြီး အသုံးပြုရလွယ်ကူသော emulators များရှိသည် - ဥပမာအားဖြင့် တူညီသော VirtualBox ကို ထည့်သွင်းပြီး အလုပ်လုပ်ပါသည်။ ဒါပေမယ့် Qemu မှာ စိတ်ဝင်စားစရာကောင်းတဲ့ အင်္ဂါရပ်များစွာရှိပါတယ်။

  • ပွင့်လင်းအရင်းအမြစ်
  • kernel driver မပါဘဲအလုပ်လုပ်နိုင်စွမ်း
  • စကားပြန်မုဒ်တွင် အလုပ်လုပ်နိုင်စွမ်း
  • အိမ်ရှင်နှင့် ဧည့်သည်ဗိသုကာ အများအပြားအတွက် ပံ့ပိုးမှု

တတိယအချက်နှင့်ပတ်သက်၍၊ တကယ်တော့ TCI မုဒ်တွင်၊ ၎င်းသည် အဓိပ္ပာယ်ဖွင့်ဆိုထားသော ဧည့်သည်စက်ညွှန်ကြားချက်များမဟုတ်သော်လည်း ၎င်းတို့ထံမှရရှိသော bytecode သည် အနှစ်သာရကို ပြောင်းလဲမည်မဟုတ်ကြောင်း ယခုရှင်းပြနိုင်သည် - တည်ဆောက်ပြီးလည်ပတ်နိုင်ရန်၊ သင်ကံကောင်းပါက၊ A C compiler သည် လုံလောက်သည် - ကုဒ်မီးစက်တစ်ခုရေးသားခြင်းကို ရွှေ့ဆိုင်းနိုင်သည်။

ယခုလည်း၊ ကျွန်ုပ်၏အားလပ်ချိန်များတွင် Qemu အရင်းအမြစ်ကုဒ်ကို နှစ်နှစ်ကြာ အေးအေးဆေးဆေး သုံးစွဲပြီးနောက်၊ ဥပမာ၊ Kolibri OS ကို သင်အသုံးပြုနိုင်ပြီးဖြစ်သည့် အလုပ်နမူနာတစ်ခု ပေါ်လာပါသည်။

Emscripten ဆိုတာ ဘာလဲ။

ယခုအချိန်တွင်၊ compiler အများအပြားပေါ်လာပြီး ယင်း၏အဆုံးရလဒ်မှာ JavaScript ဖြစ်သည်။ Type Script ကဲ့သို့ အချို့သည် ဝဘ်အတွက် အကောင်းဆုံးရေးရန် မူလက ရည်ရွယ်ထားကြသည်။ တစ်ချိန်တည်းမှာပင်၊ Emscripten သည် ရှိပြီးသား C သို့မဟုတ် C++ ကုဒ်ကိုယူပြီး ဘရောက်ဆာ-ဖတ်ရှုနိုင်သော ပုံစံသို့ စုစည်းရန် နည်းလမ်းတစ်ခုဖြစ်သည်။ ဂရန် ဒီစာမျက်နှာ ကျွန်ုပ်တို့သည် လူသိများသော ပရိုဂရမ်များ၏ ဆိပ်ကမ်းများစွာကို စုဆောင်းထားသည်။ ဒီမှာဥပမာအားဖြင့်၊ PyPy ကိုကြည့်နိုင်သည် - နည်းလမ်းအားဖြင့်၊ သူတို့သည် JIT ရှိပြီးသားဖြစ်သည်ဟုဆိုကြသည်။ တကယ်တော့၊ ပရိုဂရမ်တိုင်းကို browser တစ်ခုထဲမှာ ရိုးရိုးရှင်းရှင်းစုစည်းပြီး run လို့ မရပါဘူး - နံပါတ်တစ်ခုရှိပါတယ်။ အင်္ဂါရပ်များတူညီသောစာမျက်နှာရှိကမ္ပည်းစာတွင် "Emscripten ကိုမည်သည့်အရာကိုမဆိုစုစည်းရန် Emscripten ကိုအသုံးပြုနိုင်သည်။ ခရီးဆောင် JavaScript သို့ C/C++ ကုဒ်။ ဆိုလိုသည်မှာ၊ စံသတ်မှတ်ချက်အရ သတ်မှတ်မထားသော အပြုအမူများစွာ ရှိသည်၊ သို့သော် အများအားဖြင့် x86 တွင် အလုပ်လုပ်သည် - ဥပမာအားဖြင့်၊ အချို့သော ဗိသုကာလက်ရာများတွင် ယေဘုယျအားဖြင့် တားမြစ်ထားသည့် variables များသို့ ဟန်ချက်မညီသော ဝင်ရောက်ခွင့်၊ ယေဘုယျအားဖြင့်၊ Qemu သည် cross-platform ပရိုဂရမ်တစ်ခုဖြစ်ပြီး၊ ကျွန်တော်ယုံကြည်ချင်ပါသည်၊ ၎င်းတွင်သတ်မှတ်မထားသောအပြုအမူများစွာမပါဝင်ပါ - ၎င်းကိုယူ၍ စုစည်းပါ၊ ထို့နောက် JIT ဖြင့်အနည်းငယ်စဉ်းစားပါ - သင်ပြီးပါပြီ။ဒါပေမယ့်အဲဒါမဟုတ်ပါဘူး။ ကိစ္စ...

ဦး စွာကြိုးစားကြည့်ပါ

ယေဘူယျအားဖြင့်ပြောရလျှင်၊ ကျွန်ုပ်သည် Qemu ကို JavaScript သို့ ပို့ရန် စိတ်ကူးကို အကောင်အထည်ဖော်သည့် ပထမဆုံးလူမဟုတ်ပါ။ Emscripten ကို အသုံးပြု၍ ဖြစ်နိုင်ပါက ReactOS ဖိုရမ်တွင် မေးခွန်းတစ်ခု မေးခဲ့ပါသည်။ အစောပိုင်းကပင် Fabrice Bellard ကို ကိုယ်တိုင်ကိုယ်ကျ ပြုလုပ်ခဲ့ကြောင်း ကောလဟာလများ ရှိခဲ့သော်လည်း၊ ကျွန်ုပ်သိသလောက် JS တွင် လုံလောက်သော စွမ်းဆောင်ရည်ကို ကိုယ်တိုင်ရရှိရန် ကြိုးပမ်းမှုတစ်ခုသာဖြစ်ပြီး jslinux အကြောင်း ကျွန်ုပ်တို့ပြောနေပါသည်။ နောက်ပိုင်းတွင် Virtual x86 ကို ရေးသားခဲ့သည် - ၎င်းအတွက် ရှုပ်ထွေးမှုမရှိသော သတင်းရင်းမြစ်များကို ပို့စ်တင်ခဲ့ပြီး၊ ဆိုခဲ့သည့်အတိုင်း၊ အတုယူမှု၏ ပိုကြီးသော "လက်တွေ့ကျမှု" သည် SeaBIOS ကို Firmware အဖြစ် အသုံးပြုရန် ဖြစ်နိုင်ချေရှိသည်။ ထို့အပြင်၊ Emscripten ကို အသုံးပြု၍ Qemu ကို ပို့ရန် အနည်းဆုံး ကြိုးပမ်းမှု တစ်ခု ရှိခဲ့သည် - ကျွန်တော် ဒါကို လုပ်ရန် ကြိုးစားခဲ့သည်။ socketpairဒါပေမယ့် ကျွန်တော်နားလည်သလောက် ဖွံ့ဖြိုးတိုးတက်မှုကတော့ ရပ်တန့်နေတယ်။

ထို့ကြောင့်၊ ဤသည်မှာ အရင်းအမြစ်များဖြစ်သည်၊ ဤတွင် Emscripten ဖြစ်သည်- ၎င်းကို ယူ၍ စုစည်းပုံရသည်။ ဒါပေမယ့် Qemu မှီခိုနေတဲ့ စာကြည့်တိုက်တွေ ရှိသလို အဲဒီစာကြည့်တိုက်တွေ မှီခိုနေရတဲ့ စာကြည့်တိုက်တွေ စသည်တို့လည်း ရှိပြီး အဲဒီထဲက တစ်ခုကတော့၊ libffiဘယ် glb ပေါ်မှာမူတည်တယ်။ Emscripten အတွက် ကြီးမားသော စာကြည့်တိုက်များ အစုအဝေးတွင် တစ်ခုရှိသည်ဟူသော ကောလဟာလများ အင်တာနက်ပေါ်တွင် ရှိနေသော်လည်း ယုံကြည်ရန် အနည်းငယ် ခက်ခဲသည်- ပထမအချက်မှာ၊ ၎င်းသည် compiler အသစ်ဖြစ်ရန် မရည်ရွယ်ပါ၊ ဒုတိယ၊ အဆင့်နိမ့်လွန်းပါသည်။ စာကြည့်တိုက်ကို ကောက်ယူပြီး JS သို့ စုစည်းပါ။ ထို့အပြင် ၎င်းသည် စုစည်းထည့်သွင်းမှုများ၏ကိစ္စမဟုတ်ပါ - ဖြစ်နိုင်သည်၊ အကယ်၍ သင်သည် ၎င်းကို လှည့်ကြည့်မည်ဆိုပါက၊ အချို့သောခေါ်ဆိုမှုကွန်ဗင်းရှင်းများအတွက် သင်သည် stack ပေါ်ရှိ လိုအပ်သော အကြောင်းပြချက်များကို ဖန်တီးပြီး ၎င်းတို့မပါဘဲ function ကိုခေါ်ဆိုနိုင်သည်။ သို့သော် Emscripten သည် ဆန်းကျယ်သည့်အရာဖြစ်သည်- ထုတ်လုပ်လိုက်သောကုဒ်ကို browser JS engine optimizer နှင့်ရင်းနှီးစေရန်အတွက် အချို့သောလှည့်ကွက်များကို အသုံးပြုပါသည်။ အထူးသဖြင့်၊ relooping ဟုခေါ်သည် - လက်ခံရရှိထားသော LLVM IR ကိုအသုံးပြုထားသော ကုဒ်ဂျင်နရေတာသည် အချို့သော abstract transition ညွှန်ကြားချက်များဖြင့် ဖြစ်နိုင်ချေရှိသော ifs၊ loops စသည်တို့ကို ပြန်လည်ဖန်တီးရန် ကြိုးစားသည်။ ကောင်းပြီ၊ အကြောင်းပြချက်များသည် function ကိုမည်သို့လွှဲပြောင်းသနည်း။ ပုံမှန်အားဖြင့်၊ JS လုပ်ဆောင်ချက်များအတွက် ငြင်းခုံမှုများအနေဖြင့် ဖြစ်နိုင်ပါက stack မှမဟုတ်ဘဲ ဖြစ်နိုင်လျှင်ဖြစ်သည်။

အစပိုင်းတွင် libffi ကို JS ဖြင့် အစားထိုးပြီး စံစမ်းသပ်မှုများကို လုပ်ဆောင်ရန် စိတ်ကူးတစ်ခုရှိခဲ့သော်လည်း နောက်ဆုံးတွင် ကျွန်ုပ်၏ header ဖိုင်များကို ၎င်းတို့ရှိပြီးသား code နှင့် အလုပ်လုပ်နိုင်စေရန် မည်သို့လုပ်ဆောင်ရမည်ကို ကျွန်ုပ် ရှုပ်ထွေးသွားခဲ့ပါသည်။ သူတို့ပြောသလို "အလုပ်တွေက အရမ်းရှုပ်ထွေးနေတာလား "ငါတို့အရမ်းမိုက်နေတာလား။ ငါ libffi ကိုအခြားဗိသုကာတစ်ခုသို့ပို့ခဲ့ရသည်၊ ထို့ကြောင့်ပြောရလျှင်ကံကောင်းသည်မှာ၊ Emscripten တွင် inline assembly အတွက် macro နှစ်ခုလုံးရှိသည် (Javascript တွင်၊ ဟုတ်ပြီ၊ မည်သို့ပင်ဖြစ်စေဗိသုကာ၊ ဒါကြောင့် assembler) နှင့် fly တွင်ထုတ်ပေးသောကုဒ်များကို run နိုင်စွမ်းရှိသည်။ ယေဘူယျအားဖြင့်၊ အချိန်အတန်ကြာ platform-based libffi အပိုင်းအစများနှင့် ချိတ်ဆက်ပြီးနောက်၊ ကျွန်တော် compilable code အချို့ကို ရခဲ့ပြီး ပထမဆုံးစမ်းသပ်မှုတွင် ၎င်းကို run ခဲ့သည်။ အံ့သြဖို့ကောင်းတာက စာမေးပွဲအောင်မြင်တယ်။ ကျွန်ုပ်၏ ဉာဏ်ကြီးရှင်ကြောင့် အံ့အားသင့်သွားသည် - ရယ်စရာမဟုတ်ပါ၊ ပထမလွှတ်တင်ချိန်မှစ၍ အလုပ်ဖြစ်ခဲ့သည် - ကျွန်ုပ်သည် မျက်လုံးများကို မယုံသေးဘဲ နောက်တစ်ကြိမ်တူးရမည့်နေရာကို အကဲဖြတ်ရန် ထွက်ပေါ်လာသောကုဒ်ကို ထပ်မံကြည့်ရှုလိုက်ပါသည်။ ဤနေရာတွင် ကျွန်ုပ်သည် ဒုတိယအကြိမ် ရူးသွပ်သွားသည် - ကျွန်ုပ်၏ လုပ်ဆောင်မှုမှာ တစ်ခုတည်းသော အရာဖြစ်သည်။ ffi_call - ၎င်းသည် အောင်မြင်သောခေါ်ဆိုမှုကို အစီရင်ခံခဲ့သည်။ သူ့ဘာသာသူ ခေါ်တာ မရှိဘူး။ ဒါကြောင့် Olympiad ကျောင်းသားတိုင်း သိသာထင်ရှားတဲ့ စာမေးပွဲမှာ အမှားတစ်ခုကို ပြင်ပေးခဲ့တဲ့ ပထမဆုံး ဆွဲထုတ်မှု တောင်းဆိုချက်ကို ပေးပို့ခဲ့တယ် - ကိန်းဂဏန်း အစစ်အမှန်တွေကို နှိုင်းယှဉ်လို့မရပါဘူး။ a == b မည်သို့ပင် a - b < EPS - သင်ခန်းစာကိုလည်း မှတ်သားထားဖို့ လိုပါတယ်၊ မဟုတ်ရင် 0 ဟာ 1/3 နဲ့ ညီမျှသွားပါလိမ့်မယ်... ယေဘုယျအားဖြင့်၊ အရိုးရှင်းဆုံး စမ်းသပ်မှုတွေကို ကျော်ဖြတ်တဲ့ libffi ရဲ့ ဆိပ်ကမ်းတစ်ခုနဲ့ ထွက်လာတယ်၊ compiled - လိုအပ်မယ်လို့ ဆုံးဖြတ်ခဲ့တယ်၊ နောက်မှထည့်ပါ့မယ်။ ရှေ့ကိုကြည့်လိုက်ရင်၊ အဖြေထွက်လာတော့ compiler က နောက်ဆုံးကုဒ်မှာ libffi function ကိုတောင် မထည့်ခဲ့ဘူး။

ဒါပေမယ့် ကျွန်တော်ပြောခဲ့သလိုပဲ၊ ကန့်သတ်ချက်အချို့ရှိပါတယ်၊ အမျိုးမျိုးသောသတ်မှတ်မထားတဲ့အမူအကျင့်တွေကို အခမဲ့အသုံးပြုမှုကြားထဲမှာ၊ ပိုပြီးအဆင်မပြေတဲ့လုပ်ဆောင်ချက်ကို ဖျောက်ထားပါတယ် - ဒီဇိုင်းအားဖြင့် JavaScript သည် မျှဝေထားသောမှတ်ဉာဏ်ဖြင့် multithreading ကိုမပံ့ပိုးပါ။ မူအရ၊ ၎င်းကို အများအားဖြင့် အကြံကောင်းတစ်ခုဟုပင် ခေါ်နိုင်သော်လည်း ဗိသုကာလက်ရာ C thread များနှင့် ချိတ်ဆက်ထားသော ကုဒ်ကို ပို့ရန်အတွက် မဟုတ်ပါ။ ယေဘူယျအားဖြင့်ပြောရလျှင်၊ Firefox သည် မျှဝေလုပ်သားများကို ပံ့ပိုးပေးရန်အတွက် စမ်းသပ်နေပြီး Emscripten သည် ၎င်းတို့အတွက် pthread အကောင်အထည်ဖော်မှုတစ်ခုရှိသော်လည်း ၎င်းကို အားမကိုးချင်ပါ။ Qemu ကုဒ်မှ multithreading ကို ဖြည်းညှင်းစွာ root လုပ်ခဲ့ရသည် - ဆိုလိုသည်မှာ thread များလည်ပတ်နေသည့်နေရာကိုရှာပါ၊ ဤ thread တွင်လည်ပတ်နေသော loop ၏ကိုယ်ထည်ကို သီးခြားလုပ်ဆောင်မှုတစ်ခုအဖြစ်သို့ ရွှေ့ကာ main loop မှ တစ်ခုပြီးတစ်ခု ထို function များကို ခေါ်ပါသည်။

ဒုတိယအကြိမ်ကြိုးစားပါ။

တချိန်ချိန်မှာတော့ ပြဿနာက ရှိနေသေးတယ် ဆိုတာ သိသာထင်ရှားလာပြီး ကုဒ်ပတ်ပတ်လည်မှာ ချိုင်းထောက်တွေကို တော်ရိလျော်စွာ တွန်းထိုးလိုက်တာက ဘာကောင်းကျိုးမှ မဖြစ်စေပါဘူး။ နိဂုံး- ချိုင်းထောက်များထည့်ခြင်း လုပ်ငန်းစဉ်ကို တနည်းနည်းနဲ့ စနစ်တကျလုပ်ရန် လိုအပ်ပါသည်။ ထို့ကြောင့်၊ ထိုအချိန်က လတ်ဆတ်သော ဗားရှင်း 2.4.1 ကို ယူဆောင်သွားသည် (2.5.0 မဟုတ်ပါ။ အဘယ်ကြောင့်ဆိုသော် ဖမ်းမိခြင်း မပြုရသေးသော ဗားရှင်းအသစ်တွင် ချို့ယွင်းချက်များ ရှိနေမည်ကို မည်သူသိသနည်း၊ ကျွန်ုပ်တွင် ကျွန်ုပ်၏ ကိုယ်ပိုင် ချို့ယွင်းချက်များ လုံလောက်စွာ ရှိသည်၊ ) ပထမတစ်ချက်ကတော့ လုံခြုံစွာပြန်ရေးဖို့ပါပဲ။ thread-posix.c. ကောင်းပြီ၊ ဆိုလိုသည်မှာ ဘေးကင်းသည်- တစ်စုံတစ်ဦးသည် ပိတ်ဆို့ခြင်းကို ဖြစ်စေသော လုပ်ဆောင်ချက်တစ်ခုကို လုပ်ဆောင်ရန် ကြိုးစားပါက၊ လုပ်ဆောင်ချက်ကို ချက်ချင်းခေါ်သည်။ abort() - ဟုတ်ပါတယ်၊ ဒါက ပြဿနာအားလုံးကို တစ်ပြိုင်နက်တည်း မဖြေရှင်းနိုင်ပေမယ့် အနည်းဆုံးတော့ တစ်နည်းနည်းနဲ့ ကိုက်ညီမှုမရှိတဲ့ အချက်အလက်တွေကို တိတ်တဆိတ် လက်ခံတာထက် ပိုသာယာပါတယ်။

ယေဘုယျအားဖြင့်၊ Emscripten ရွေးချယ်မှုများသည် ကုဒ်ကို JS သို့ ပို့ရာတွင် အလွန်အသုံးဝင်သည်။ -s ASSERTIONS=1 -s SAFE_HEAP=1 - ၎င်းတို့သည် သတ်မှတ်မထားသော လိပ်စာသို့ ခေါ်ဆိုမှုများကဲ့သို့သော သတ်မှတ်မထားသော အပြုအမူအချို့ကို ဖမ်းမိသည် (ထိုကဲ့သို့သော ရိုက်ထည့်ထားသော array များအတွက် ကုဒ်များနှင့် လုံးဝကိုက်ညီမှုမရှိပါ။ HEAP32[addr >> 2] = 1) သို့မဟုတ် မှားယွင်းသော အကြောင်းပြချက်များဖြင့် လုပ်ဆောင်ချက်တစ်ခုကို ခေါ်ဆိုခြင်း။

စကားမစပ်၊ ချိန်ညှိမှုအမှားများသည် သီးခြားပြဿနာတစ်ခုဖြစ်သည်။ ငါပြောပြီးသားအတိုင်း၊ Qemu တွင် ကုဒ်ထုတ်လုပ်ခြင်း TCI (သေးငယ်သောကုဒ်ဘာသာပြန်) အတွက် "degenerate" စကားပြန်နောက်ကွယ်တွင်ရှိပြီး၊ သင်ကံကောင်းပါက၊ C compiler သည် လုံလောက်သော ဗိသုကာအသစ်တစ်ခုတွင် Qemu ကိုတည်ဆောက်ပြီး run ရန်၊ သော့ချက်စာလုံးများ "မင်းကံကောင်းရင်". ကံမကောင်းခဲ့သဖြင့် ၎င်း၏ bytecode ကိုခွဲခြမ်းစိတ်ဖြာသောအခါ TCI သည် unaligned access ကိုအသုံးပြုကြောင်းတွေ့ရှိခဲ့ရသည်။ ဆိုလိုသည်မှာ၊ သေချာပေါက်အဆင့်သတ်မှတ်ထားသောဝင်ရောက်ခွင့်ရှိသော ARM နှင့်အခြားဗိသုကာအမျိုးအစားအားလုံးတွင်၊ Qemu သည် မူရင်းကုဒ်ကိုထုတ်ပေးသည့်ပုံမှန် TCG နောက်ခံရှိသောကြောင့် Compile ဖြစ်သော်လည်း ၎င်းတို့တွင် TCI အလုပ်လုပ်မည်ရှိမရှိသည် အခြားမေးခွန်းတစ်ခုဖြစ်သည်။ မည်သို့ပင်ဆိုစေကာမူ TCI စာရွက်စာတမ်းသည် အလားတူအရာတစ်ခုကို ရှင်းရှင်းလင်းလင်းဖော်ပြခဲ့သည်။ ရလဒ်အနေဖြင့်၊ Qemu ၏အခြားအစိတ်အပိုင်းတွင်ရှာဖွေတွေ့ရှိခဲ့သောကုဒ်သို့ ညီညွတ်မှုမရှိသောဖတ်ရှုခြင်းအတွက် လုပ်ဆောင်ချက်ခေါ်ဆိုမှုများကို ထည့်သွင်းခဲ့သည်။

အမှိုက်ပုံ ပျက်စီးခြင်း။

ရလဒ်အနေဖြင့် TCI သို့ အချိုးမညီသောဝင်ရောက်မှုကို ပြုပြင်လိုက်သည်၊ ၎င်းကို ပရိုဆက်ဆာ၊ RCU နှင့် အခြားသေးငယ်သောအရာအချို့ဟုခေါ်သော ပင်မလှည့်ပတ်တစ်ခုကို ဖန်တီးခဲ့သည်။ ဒါကြောင့် ရွေးချယ်ခွင့်နဲ့ Qemu ကို ဖွင့်လိုက်ပါ။ -d exec,in_asm,out_asmဆိုလိုသည်မှာ သင်သည် မည်သည့်ကုဒ်တုံးများကို လုပ်ဆောင်နေကြောင်း ပြောရန် လိုအပ်ပြီး ဧည့်သည်ကုဒ်သည် မည်သည့်ကုဒ်ဖြစ်သည်ကို ရေးသားရန် ထုတ်လွှင့်ချိန်တွင်လည်း host code ဖြစ်လာသည် (ဤကိစ္စတွင်၊ bytecode)။ ၎င်းသည် စတင်သည်၊ ဘာသာပြန်ဘလောက်များစွာကို လုပ်ဆောင်သည်၊ RCU သည် ယခုစတင်တော့မည်ဖြစ်ပြီး ... ပျက်သွားသည် abort() function တစ်ခုအတွင်း free(). လုပ်ဆောင်ချက်ကို ပေါင်းစပ်ခြင်းဖြင့် free() ခွဲဝေချထားပေးသည့်မှတ်ဉာဏ်မတိုင်မီ ရှစ်ဘိုက်တွင်ရှိသော အမှိုက်ပုံဘလောက်၏ ခေါင်းစီးတွင် ပိတ်ဆို့အရွယ်အစား သို့မဟုတ် အလားတူအရာများအစား အမှိုက်များ ရှိနေကြောင်း ကျွန်ုပ်တို့ ရှာဖွေတွေ့ရှိနိုင်ခဲ့သည်။

အမှိုက်ပုံပျက်စီးခြင်း - ဘယ်လောက်ချစ်စရာကောင်းတဲ့... ဒီလိုအခြေအနေမျိုးမှာ၊ တူညီတဲ့အရင်းအမြစ်များမှ (ဖြစ်နိုင်ရင်) အသုံးဝင်တဲ့ဆေးတစ်လက်ရှိပါတယ်၊ မူရင်း binary တစ်ခုကို စုပြီး Valgrind အောက်မှာ run လိုက်ပါ။ အချိန်အတော်ကြာပြီးနောက်၊ ဒွိစုံ အဆင်သင့်ဖြစ်နေပါပြီ။ ၎င်းကို တူညီသောရွေးချယ်မှုများဖြင့် စတင်လိုက်သည် - အမှန်တကယ် ကွပ်မျက်ခြင်းသို့ မရောက်ရှိမီ အစပျိုးချိန်တွင်ပင် ပျက်သွားပါသည်။ မနှစ်မြို့ဖွယ်ဖြစ်သည်၊ ဟုတ်ပါတယ်၊ အရင်းအမြစ်များသည်အတိအကျတူညီခြင်းမရှိပါ၊ အံ့သြစရာမဟုတ်ပါ၊ အဘယ်ကြောင့်ဆိုသော် configure သည်အနည်းငယ်ကွဲပြားသောရွေးချယ်စရာများကိုရှာဖွေထားသောကြောင့်၊ သို့သော်ကျွန်ုပ်တွင် Valgrind ရှိသည် - ပထမဦးစွာဤ bug ကိုငါပြုပြင်ပါ၊ ထို့နောက်ကံကောင်းပါက၊ မူရင်း ပေါ်လာပါမည်။ ငါ Valgrind အောက်တွင် တူညီသောအရာကို လုပ်ဆောင်နေပါသည်... Y-y-y, y-y-y, uh-uh၊ ၎င်းသည် စတင်ခဲ့ပြီး၊ အစပြုခြင်းအား ပုံမှန်အတိုင်းဖြတ်သန်းသွားခဲ့ပြီး မှားယွင်းနေသော memory access အကြောင်း တစ်ချက်မျှသတိမပေးဘဲ မှားယွင်းနေသော memory access အကြောင်းကို တစ်ချက်မျှသတိမပေးဘဲ မူရင်းအတိုင်း ကူးပြောင်းသွားပါသည်။ သူတို့ပြောသလိုပဲ အသက်က ဒီအတွက် ကျွန်မကို မပြင်ဆင်ထားဘူး - Walgrind အောက်မှာ လွှင့်တင်လိုက်တဲ့အခါ ပျက်စီးသွားတဲ့ ပရိုဂရမ်ဟာ ပျက်သွားတော့တာပါပဲ။ အဲဒါက ဆန်းကြယ်တယ်။ ကျွန်ုပ်၏ယူဆချက်မှာ ကနဦးလုပ်ဆောင်မှုအတွင်း ပျက်စီးသွားပြီးနောက် လက်ရှိညွှန်ကြားချက်၏အနီးတစ်ဝိုက်တွင် တစ်ကြိမ်၊ gdb သည် အလုပ်အားပြသခဲ့သည်၊ memset-a ဖြင့် မှန်ကန်သော pointer ဖြင့်လည်းကောင်း အသုံးပြုခြင်း။ mmx, သို့မဟုတ် xmm မှတ်ပုံတင်ခြင်း၊ ယုံကြည်ရန် ခက်ခဲနေသော်လည်း ၎င်းသည် ချိန်ညှိမှု ချို့ယွင်းချက်မျိုး ဖြစ်ကောင်းဖြစ်နိုင်သည်။

ကောင်းပြီ၊ Valgrind သည် ဤနေရာတွင် ကူညီပုံမပေါ်ပါ။ ဤနေရာတွင် စက်ဆုပ်ရွံရှာဖွယ်အရှိဆုံးအရာသည် စတင်ခဲ့သည်- အရာအားလုံးသည်ပင် စတင်နေပုံရသော်လည်း လွန်ခဲ့သော သန်းနှင့်ချီသော ညွှန်ကြားချက်များ ဖြစ်ပေါ်လာနိုင်သည့် အဖြစ်အပျက်တစ်ခုကြောင့် လုံးဝမသိရသေးသော အကြောင်းပြချက်များဖြင့် ပျက်ကျသွားသည်။ အချိန်အတော်ကြာအောင် ဘယ်လိုချဉ်းကပ်ရမှန်းတောင် မသဲကွဲဘူး။ အဆုံးမှာတော့ ငါထိုင်ပြီး အမှားရှာနေသေးတယ်။ ခေါင်းစီးဖြင့် ပြန်လည်ရေးသားထားသည့် ပရင့်ထုတ်ခြင်းတွင် ၎င်းသည် နံပါတ်ကဲ့သို့မဟုတ်သော်လည်း binary data အမျိုးအစားအချို့ကို ပြသခဲ့သည်။ ကြည့်ပြီး၊ ဤ binary string ကို BIOS ဖိုင်တွင် တွေ့ရှိခဲ့သည် - ဆိုလိုသည်မှာ၊ ၎င်းသည် ကြားခံပြည့်လျှံမှုဖြစ်ကြောင်း ကျိုးကြောင်းဆီလျော်စွာ ယုံကြည်စွာပြောနိုင်ပြီဖြစ်ပြီး ၎င်းကို ဤကြားခံတွင် ရေးသားထားကြောင်းပင် ရှင်းပါသည်။ ဒါဆိုရင် Emscripten မှာ ကံကောင်းထောက်မစွာ၊ ကံကောင်းစွာနဲ့ပဲ၊ လိပ်စာနေရာကို randomization မလုပ်ထားဘူး၊ အဲဒီထဲမှာ အပေါက်တွေ မရှိဘူး၊ ဒါကြောင့် နောက်ဆုံး launch က pointer နဲ့ data ထုတ်ပေးဖို့အတွက် code ရဲ့ အလယ်တစ်နေရာရာမှာ ရေးလို့ရပါတယ်။ ဒေတာကိုကြည့်ပါ၊ ညွှန်ကိန်းကိုကြည့်ပါ၊ ၎င်းသည်မပြောင်းလဲပါက၊ တွေးတောရန်အစားအစာကိုရယူပါ။ အပြောင်းအလဲတစ်ခုခုပြီးနောက် လင့်ခ်ချိတ်ရန် မိနစ်အနည်းငယ်ကြာသော်လည်း သင်ဘာလုပ်နိုင်သနည်း။ ရလဒ်အနေဖြင့်၊ BIOS အား ယာယီကြားခံမှဧည့်သည်မှတ်ဉာဏ်သို့ကူးယူထားသည့် သီးခြားလိုင်းတစ်ခုကိုတွေ့ရှိခဲ့သည် - အမှန်ပင်၊ ကြားခံတွင် နေရာအလုံအလောက်မရှိပါ။ ထိုထူးဆန်းသော ကြားခံလိပ်စာ၏ ရင်းမြစ်ကို ရှာဖွေခြင်းသည် လုပ်ဆောင်ချက်တစ်ခု ဖြစ်ပေါ်ခဲ့သည်။ qemu_anon_ram_alloc ဖိုင်ထဲမှာ oslib-posix.c - ဤနေရာတွင် ယုတ္တိရှိပါသည်- တစ်ခါတစ်ရံတွင် လိပ်စာကို 2 MB အရွယ်အစားကြီးသော စာမျက်နှာသို့ ချိန်ညှိရန် အသုံးဝင်နိုင်သည်၊ ဤအတွက် ကျွန်ုပ်တို့မေးပါမည်။ mmap အရင်ဆုံး နည်းနည်းပိုပြီးတော့ အကူအညီနဲ့ ပိုလျှံတာကို ပြန်ပေးမယ်။ munmap. ထိုသို့သော ချိန်ညှိမှုမလိုအပ်ပါက 2 MB အစား ရလဒ်ကို ညွှန်ပြပါမည်။ getpagesize() - mmap ညှိထားတဲ့လိပ်စာကို ပေးနေတုန်းပဲ... ဒီတော့ Emscripten မှာ mmap ခေါ်ဆိုရုံပါပဲ။ mallocဒါပေမယ့် စာမျက်နှာပေါ်မှာ ညှိမနေပါဘူး။ ယေဘူယျအားဖြင့်၊ လအနည်းငယ်ကြာအောင် ငါ့ကိုစိတ်ပျက်စေသော ချို့ယွင်းချက်တစ်ခုကို အပြောင်းအလဲတစ်ခုဖြင့် ပြင်ပေးသည်။ двух လိုင်းများ။

ခေါ်ဆိုမှုလုပ်ဆောင်ချက်များ၏အင်္ဂါရပ်များ

ယခုဆိုလျှင် ပရိုဆက်ဆာသည် တစ်ခုခုကို ရေတွက်နေပါသည်၊ Qemu ပျက်သွားသော်လည်း မျက်နှာပြင်သည် မပွင့်တော့ဘဲ ပရိုဆက်ဆာသည် အထွက်နှုန်းဖြင့် အကဲဖြတ်ကာ အကွက်များထဲသို့ အမြန်ရောက်သွားပါသည်။ -d exec,in_asm,out_asm. အယူအဆတစ်ခု ထွက်ပေါ်လာသည်- အချိန်တိုင်းစက် နှောင့်ယှက်မှုများ (သို့မဟုတ် ယေဘုယျအားဖြင့် ကြားဖြတ်များအားလုံး) မရောက်ပါ။ အမှန်ပင်၊ အကြောင်းတစ်ခုခုကြောင့် အလုပ်ဖြစ်ခဲ့သည့် ဇာတိစည်းဝေးပွဲမှ ကြားဖြတ်များကို ဝက်အူဖြုတ်ပါက အလားတူပုံတစ်ခု ရရှိမည်ဖြစ်သည်။ သို့သော် ၎င်းသည် အဖြေလုံးဝမဟုတ်ပါ- အထက်ဖော်ပြပါရွေးချယ်မှုဖြင့် ထုတ်ပြန်ထားသော ခြေရာများကို နှိုင်းယှဉ်ကြည့်ရာ ကွပ်မျက်ရေးလမ်းကြောင်းများသည် အလွန်စောစီးစွာ ကွဲပြားသွားကြောင်း ပြသခဲ့သည်။ ဤနေရာတွင် launcher ကို အသုံးပြု၍ မှတ်တမ်းတင်ထားသည်ကို နှိုင်းယှဉ်သည်ဟု ဆိုရပါမည်။ emrun native assembly ၏ output ဖြင့် debugging output သည် လုံးဝစက်ပိုင်းဆိုင်ရာလုပ်ငန်းစဉ်မဟုတ်ပါ။ ဘရောက်ဆာမှာ အလုပ်လုပ်တဲ့ ပရိုဂရမ်တစ်ခုနဲ့ ဘယ်လို ချိတ်ဆက်သလဲဆိုတာ အတိအကျ မသိပါဘူး။ emrunသို့သော် အထွက်ရှိ လိုင်းအချို့ကို ပြန်လည်စီစဉ်ထားသောကြောင့် ကွဲပြားမှုမှာ လမ်းကြောင်းများ ကွဲပြားသွားသည်ဟု ယူဆရန် အကြောင်းပြချက်မရှိသေးပါ။ ယေဘုယျအားဖြင့် ညွှန်ကြားချက်များအတိုင်း ထင်ရှားလာခဲ့သည်။ ljmpl မတူညီသော လိပ်စာများသို့ ကူးပြောင်းမှု ရှိပြီး၊ ထုတ်လုပ်လိုက်သော bytecode သည် အခြေခံအားဖြင့် ကွဲပြားသည်- တစ်ခုတွင် helper function ကို ခေါ်ရန် ညွှန်ကြားချက်တစ်ခု ပါရှိသည်၊ နောက်တစ်ခုသည် မရှိပါ။ ညွှန်ကြားချက်များကို ဂူဂဲလ်လုပ်ပြီး ဤညွှန်ကြားချက်များကို ဘာသာပြန်ဆိုထားသည့် ကုဒ်များကို လေ့လာပြီးနောက်၊ ပထမဆုံးအနေနှင့် မှတ်ပုံတင်ခြင်းမပြုမီ ချက်ချင်းပင် ထင်ရှားလာပါသည်။ cr0 ပရိုဆက်ဆာကို ကာကွယ်ထားသည့်မုဒ်သို့ ပြောင်းပေးသည့် အထောက်အကူကို အသုံးပြု၍ အသံဖမ်းခြင်းကို ပြုလုပ်ခဲ့ပြီး ဒုတိယအချက်မှာ js ဗားရှင်းသည် ကာကွယ်ထားသည့်မုဒ်သို့ ဘယ်တော့မှ မပြောင်းခဲ့ပါ။ သို့သော်အမှန်မှာ Emscripten ၏နောက်ထပ်အင်္ဂါရပ်တစ်ခုမှာ ညွှန်ကြားချက်များအကောင်အထည်ဖော်ခြင်းကဲ့သို့သော ကုဒ်ကိုသည်းခံရန် တွန့်ဆုတ်နေခြင်းဖြစ်သည်၊ call TCI တွင်၊ မည်သည့် function pointer သည် type ကိုဖြစ်စေသည်။ long long f(int arg0, .. int arg9) - လုပ်ဆောင်ချက်များကို မှန်ကန်သော အကြောင်းပြချက်များဖြင့် ခေါ်ဆိုရပါမည်။ ဤစည်းမျဉ်းကို ချိုးဖောက်ပါက၊ အမှားရှာပြင်ခြင်းဆက်တင်များပေါ် မူတည်၍ ပရိုဂရမ်သည် ပျက်စီးသွားလိမ့်မည် (ကောင်းသည်) သို့မဟုတ် မှားယွင်းသောလုပ်ဆောင်ချက်ကို လုံးဝခေါ်ဆိုနိုင်သည် (အမှားရှာရန် ဝမ်းနည်းစရာဖြစ်လိမ့်မည်)။ တတိယရွေးချယ်စရာတစ်ခုလည်းရှိပါသည် - အကြောင်းပြချက်များပေါင်းထည့် / ဖယ်ရှားသည့် wrappers မျိုးဆက်ကိုဖွင့်ထားသော်လည်း၊ အမှန်တကယ်အားဖြင့် ကျွန်ုပ်သည် ထုပ်ပိုးမှုတစ်ရာကျော်သာလိုအပ်သော်လည်း၊ ဤထုပ်ပိုးမှုများသည် နေရာများစွာယူနေပါသည်။ ဤအရာသည် အလွန်ဝမ်းနည်းစရာကောင်းသည်၊ သို့သော် ပို၍လေးနက်သောပြဿနာတစ်ခုဖြစ်လာခဲ့သည်- wrapper လုပ်ဆောင်ချက်များ၏ ထုတ်ပေးသည့်ကုဒ်တွင်၊ အကြောင်းပြချက်များကို ပြောင်းလဲကာ ပြောင်းလဲသွားသော်လည်း တစ်ခါတစ်ရံတွင် ထုတ်ပေးထားသော အကြောင်းပြချက်များနှင့် လုပ်ဆောင်ချက်ကို မခေါ်ပါ - ကောင်းစွာ၊ အလားတူ၊ ကျွန်ုပ်၏ libffi အကောင်အထည်ဖော်မှု။ ဆိုလိုသည်မှာ၊ အချို့သောအကူအညီများသည် ရိုးရိုးရှင်းရှင်း အသတ်မခံရပါ။

ကံကောင်းထောက်မစွာ၊ Qemu တွင် header file ကဲ့သို့သော header file ပုံစံဖြင့် စက်ဖတ်နိုင်သော အထောက်အကူစာရင်းများ ရှိသည်။

DEF_HELPER_0(lock, void)
DEF_HELPER_0(unlock, void)
DEF_HELPER_3(write_eflags, void, env, tl, i32)

၎င်းတို့ကို ရယ်စရာကောင်းလောက်အောင် အသုံးပြုကြသည်- ပထမ၊ မက်ခရိုများကို အထူးဆန်းဆုံးနည်းလမ်းဖြင့် ပြန်လည်သတ်မှတ်ထားသည်။ DEF_HELPER_nပြီးမှ ဖွင့်ပါ။ helper.h. မက်ခရိုကို ဖွဲ့စည်းတည်ဆောက်ပုံ အစပျိုးလုပ်ဆောင်မှု နှင့် ကော်မာအဖြစ် ချဲ့ထွင်ထားသည့်အတိုင်းအတာအထိ၊ ထို့နောက် ခင်းကျင်းတစ်ခုကို သတ်မှတ်ပြီး ဒြပ်စင်များအစား - #include <helper.h> ရလဒ်အနေနဲ့ နောက်ဆုံးတော့ အလုပ်မှာ စာကြည့်တိုက်ကို စမ်းကြည့်ခွင့်ရခဲ့တယ်။ pyparsingနှင့် ၎င်းတို့လိုအပ်သည့် လုပ်ဆောင်ချက်များအတွက် အတိအကျ အဆိုပါထုပ်ပိုးမှုများကို ထုတ်ပေးသည့် ဇာတ်ညွှန်းတစ်ခုကို ရေးသားခဲ့သည်။

ထို့ကြောင့်၊ ထို့နောက်တွင် ပရိုဆက်ဆာသည် အလုပ်လုပ်ပုံပေါ်သည်။ memtest86+ သည် ဇာတိစုဝေးမှုတွင် လုပ်ဆောင်နိုင်သော်လည်း မျက်နှာပြင်ကို မည်သည့်အခါမှ အစမဖော်နိုင်သောကြောင့် ဖြစ်ပုံရသည်။ ဤနေရာတွင် Qemu block I/O ကုဒ်ကို ရိုးရိုးစဉ်ဆက်များဖြင့် ရေးသားထားကြောင်း ရှင်းလင်းရန် လိုအပ်ပါသည်။ Emscripten တွင် ၎င်း၏ အလွန်ခက်ခဲသော အကောင်အထည်ဖော်မှု ပါရှိသော်လည်း ၎င်းကို Qemu ကုဒ်တွင် ပံ့ပိုးထားရန် လိုအပ်သေးပြီး ပရိုဆက်ဆာကို ယခု အမှားရှာပြင်နိုင်သည်- Qemu သည် ရွေးချယ်မှုများကို ပံ့ပိုးပေးသည် -kernel, -initrd, -appendပိတ်ဆို့ကိရိယာများကို လုံးဝအသုံးမပြုဘဲ Linux သို့မဟုတ် ဥပမာ memtest86+ ကို သင်စတင်နိုင်သည်။ သို့သော်ဤတွင်ပြဿနာဖြစ်ပါသည်- ဇာတိစည်းဝေးပွဲတွင်တစ်ဦးသည်ရွေးချယ်စရာနှင့်အတူ console သို့ Linux kernel အထွက်ကိုမြင်နိုင်သည်။ -nographicနှင့် ဘရောက်ဆာမှ စတင်သည့်နေရာမှ terminal သို့ output မရှိပါ။ emrunမလာဘူး။ ဆိုလိုသည်မှာ ရှင်းရှင်းလင်းလင်း မသိရပေ- ပရိုဆက်ဆာ အလုပ်မလုပ်ပါ သို့မဟုတ် ဂရပ်ဖစ်အထွက် အလုပ်မလုပ်ပါ။ နောက်တော့ နည်းနည်းစောင့်ရတာပေါ့။ “ပရိုဆက်ဆာက အိပ်မနေပါဘူး၊ ဒါပေမယ့် ဖြည်းညင်းစွာ မှိတ်တုတ်မှိတ်တုတ်ပြနေတယ်” လို့ ထွက်ဆိုခဲ့ပြီး ငါးမိနစ်ခန့်အကြာတွင် kernel သည် ကွန်ဆိုးလ်ပေါ်သို့ မက်ဆေ့ချ်များစွာကို လွှင့်တင်ကာ ဆက်ဆွဲသွားခဲ့သည်။ ပရိုဆက်ဆာသည် ယေဘူယျအားဖြင့် အလုပ်လုပ်သည်၊ SDL2 နှင့် အလုပ်လုပ်ရန်အတွက် ကုဒ်ကို တူးဖော်ရန် လိုအပ်ကြောင်း ရှင်းရှင်းလင်းလင်း သိလာသည်။ ကံမကောင်းစွာဖြင့်၊ ဤစာကြည့်တိုက်ကို မည်သို့အသုံးပြုရမည်ကို ကျွန်ုပ်မသိသောကြောင့် အချို့နေရာများတွင် ကျွန်ုပ်သည် ကျပန်းလုပ်ဆောင်ခဲ့ရပါသည်။ တစ်ချိန်ချိန်တွင်၊ မျဉ်းပြိုင် 0 သည် အပြာရောင်နောက်ခံတွင် ဖန်သားပြင်ပေါ်တွင် တောက်လျှောက် ပေါ်လာပြီး အတွေးအချို့ကို အကြံပြုပေးသည်။ အဆုံးတွင်၊ သင် Ctrl-Alt-n ကိုအသုံးပြု၍ ပြောင်းနိုင်သည့်ကြားရှိ ရုပ်ပိုင်းဆိုင်ရာဝင်းဒိုးတစ်ခုတွင် Qemu သည် virtual windows အများအပြားကိုဖွင့်ရခြင်းဖြစ်သည်- ၎င်းသည် native build တွင်အလုပ်လုပ်သော်လည်း Emscripten တွင်မဟုတ်ပါ။ မလိုအပ်တဲ့ windows တွေကို ဖယ်ရှားရရင် ရွေးချယ်စရာတွေကို အသုံးပြုပါ။ -monitor none -parallel none -serial none ဖရိန်တစ်ခုစီရှိ ဖန်သားပြင်တစ်ခုလုံးကို အတင်းပြန်ဆွဲရန် ညွှန်ကြားချက်များ၊ အရာအားလုံး ရုတ်တရက် အလုပ်ဖြစ်ခဲ့သည်။

လုပ်ရိုးလုပ်စဉ်များ

ထို့ကြောင့်၊ ဘရောင်ဇာတွင် အတုယူခြင်းသည် အလုပ်လုပ်သော်လည်း၊ ပိတ်ဆို့ခြင်း I/O မရှိသောကြောင့် ၎င်းတွင် စိတ်ဝင်စားဖွယ်ကောင်းသော single-floppy တစ်ခုခုကို သင်လုပ်ဆောင်နိုင်သည် - သင်သည် coroutines အတွက် ပံ့ပိုးမှုကို အကောင်အထည်ဖော်ရန် လိုအပ်ပါသည်။ Qemu တွင် ကော်ရိုတင်းနောက်ကွယ်တွင် အများအပြားရှိနှင့်ပြီးဖြစ်သော်လည်း JavaScript နှင့် Emscripten ကုဒ်ထုတ်လုပ်သူ၏ သဘောသဘာဝကြောင့်၊ သင်သည် juggling stacks များကို မစတင်နိုင်ပါ။ "အရာရာ မရှိတော့ဘူး၊ အင်္ဂတေကို ဖယ်ရှားနေတယ်" ဟု ထင်ရသော်လည်း Emscripten developer များသည် အရာအားလုံးကို ဂရုစိုက်ပြီးဖြစ်သည်။ ၎င်းသည် ရယ်စရာကောင်းလောက်အောင် အကောင်အထည်ဖော်သည်- ဤသံသယဖြစ်ဖွယ်ကဲ့သို့သော လုပ်ဆောင်ချက်ခေါ်ဆိုမှုတစ်ခုကို ခေါ်ကြပါစို့ emscripten_sleep Asyncify ယန္တရားကို အသုံးပြု၍ အခြားများစွာသော အခြားအရာများ၊ ညွှန်ပြချက်ခေါ်ဆိုမှုများနှင့် ခေါ်ဆိုမှုများသည် ယခင်အမှုတွဲနှစ်ခုအနက်မှ တစ်ခုသည် အစုအဝေးတွင် ထပ်မံဖြစ်ပေါ်နိုင်သည့် မည်သည့်လုပ်ဆောင်ချက်ကိုမဆို ညွှန်ပြသည့်ခေါ်ဆိုမှုများနှင့် ခေါ်ဆိုမှုများ။ ယခု၊ သံသယဖြစ်ဖွယ်ခေါ်ဆိုမှုတစ်ခုစီမတိုင်မီ၊ ကျွန်ုပ်တို့သည် တူညီသောအကြောင်းအရာတစ်ခုကို ရွေးမည်ဖြစ်ပြီး၊ ခေါ်ဆိုပြီးနောက်တွင်၊ ကျွန်ုပ်တို့သည် အပျက်သဘောဆောင်သောခေါ်ဆိုမှုတစ်ခု ဖြစ်ပေါ်ခဲ့သည်ရှိမရှိ စစ်ဆေးမည်ဖြစ်ပြီး ၎င်းတွင်ရှိနေပါက၊ ဤ async ဆက်စပ်မှုတွင် ဒေသတွင်း variable အားလုံးကို သိမ်းဆည်းမည်ဖြစ်ပြီး မည်သည့်လုပ်ဆောင်ချက်ကို ဖော်ပြပါ ဆက်လက်လုပ်ဆောင်ရန် လိုအပ်သည့်အခါတွင် ထိန်းချုပ်မှုကို လွှဲပြောင်းရန်နှင့် လက်ရှိလုပ်ဆောင်မှုမှ ထွက်ရန်။ ဤနေရာတွင် အကျိုးသက်ရောက်မှုကို လေ့လာရန် နယ်ပယ်ရှိသည်။ ဖြုန်းတီးခြင်း။ — asynchronous ခေါ်ဆိုမှုမှ ပြန်လာပြီးနောက် ကုဒ်ဆက်လက်လုပ်ဆောင်မှု လိုအပ်ချက်များ အတွက်၊ ကွန်ပြူတာသည် သံသယဖြစ်ဖွယ်ခေါ်ဆိုမှုတစ်ခုပြီးနောက် စတင်သည့် လုပ်ဆောင်ချက်၏ "stubs" ကို ထုတ်ပေးသည် — ဤကဲ့သို့သော- သံသယဖြစ်ဖွယ်ခေါ်ဆိုမှုများရှိပါက၊ လုပ်ဆောင်ချက်ကို တစ်နေရာရာသို့ ချဲ့ထွင်လိမ့်မည် n/2 အကြိမ်များ — ၎င်းသည် ဆဲဆိုကြိမ်းမောင်းခြင်း ဖြစ်နိုင်ချေရှိသော ခေါ်ဆိုမှုတိုင်းပြီးနောက်၊ မူရင်းလုပ်ဆောင်ချက်တွင် အချို့သော ဒေသန္တရကိန်းရှင်များကို သိမ်းဆည်းထည့်သွင်းရန် လိုအပ်ကြောင်း မှတ်သားထားပါ။ နောက်ပိုင်းတွင်၊ Python တွင် ရိုးရှင်းသော ဇာတ်ညွှန်းကိုပင် ရေးသားခဲ့ရပြီး ၎င်းသည် "အညီအမျှ ၎င်းတို့ကိုယ်တိုင်ဖြတ်သန်းခွင့်မပြုပါ" ဟု ယူဆရသော အထူးအသုံးများသည့် လုပ်ဆောင်ချက်အစုံအပေါ် အခြေခံ၍ (ဆိုလိုသည်မှာ stack ပရိုမိုးရှင်းနှင့် ယခုဖော်ပြခဲ့သည့်အရာအားလုံးသည် မလုပ်ဆောင်နိုင်ပါ။ ၎င်းတို့တွင် အလုပ်လုပ်သည်)၊ ဤလုပ်ဆောင်ချက်များကို ပြိုင်တူမညီဟု မယူဆစေရန် လုပ်ဆောင်ချက်များကို compiler မှ လျစ်လျူရှုသင့်သည့် ညွှန်ပြချက်များမှတစ်ဆင့် ခေါ်ဆိုမှုများကို ညွှန်ပြသည်။ ပြီးတော့ 60 MB အောက်ရှိတဲ့ JS ဖိုင်တွေက အရမ်းများနေတယ် - အနည်းဆုံး 30 ဆိုပါစို့။ assembly script တစ်ခုကို သတ်မှတ်ပြီးတာနဲ့ linker options တွေကို မတော်တဆ ပစ်ချလိုက်ပေမယ့်၊ -O3. ကျွန်ုပ်ထုတ်လုပ်လိုက်သောကုဒ်ကို လုပ်ဆောင်ပြီး Chromium သည် မမ်မိုရီကိုစားကာ ပျက်စီးသွားပါသည်။ သူဒေါင်းလုဒ်ဆွဲဖို့ကြိုးစားနေတာကို အမှတ်တမဲ့ကြည့်မိတယ်... အင်း၊ ဘာပြောရမှာလဲ၊ 500+ MB Javascript ကို စဉ်းစဉ်းစားစားလေ့လာပြီး အကောင်းဆုံးဖြစ်အောင်လုပ်ခိုင်းရင် ငါလည်း အေးခဲသွားလိမ့်မယ်။

ကံမကောင်းစွာပဲ၊ Asyncify ပံ့ပိုးမှုစာကြည့်တိုက်ကုဒ်ရှိ စစ်ဆေးမှုများသည် လုံး၀ လိုက်လျောညီထွေမဖြစ်ပါ။ longjmp-s ကို virtual ပရိုဆက်ဆာကုဒ်တွင်အသုံးပြုသော်လည်း၊ ဤစစ်ဆေးမှုများကိုပိတ်ပြီး အရာအားလုံးအဆင်ပြေနေသကဲ့သို့ ဆက်စပ်အကြောင်းအရာများကို အတင်းအကျပ်ပြန်လုပ်သည့် သေးငယ်သော patch ပြီးနောက်၊ ကုဒ်အလုပ်လုပ်သည်။ ထို့နောက် ထူးဆန်းသည့်အရာတစ်ခုစတင်ခဲ့သည်- တစ်ခါတစ်ရံတွင် synchronization ကုဒ်ကို စစ်ဆေးမှုများစတင်ခဲ့သည်- ကုဒ်ကို ပျက်သွားအောင် လုပ်ဆောင်သည့် ယုတ္တိဗေဒအရ၊ ၎င်းကို ပိတ်ဆို့ထားသင့်သည်ဆိုပါက၊ တစ်စုံတစ်ဦးသည် ဖမ်းယူထားပြီးဖြစ်သော mutex ကို ဖမ်းယူရန် ကြိုးစားခဲ့သည်။ ကံကောင်းထောက်မစွာ၊ ၎င်းသည် နံပါတ်စဉ်တပ်ထားသောကုဒ်တွင် ယုတ္တိဗေဒပြဿနာတစ်ခုမဟုတ်ခဲ့ပေ - ကျွန်ုပ်သည် Emscripten မှပေးသော စံပင်မကွင်းပတ်လုပ်ဆောင်နိုင်စွမ်းကို ရိုးရိုးရှင်းရှင်းအသုံးပြုနေသော်လည်း တစ်ခါတစ်ရံတွင် ပြိုင်တူမညီသောခေါ်ဆိုမှုသည် stack အား လုံး၀ရှင်းလင်းသွားမည်ဖြစ်ပြီး ထိုအချိန်တွင် ပျက်သွားမည်ဖြစ်သည်။ setTimeout main loop မှ - ထို့ကြောင့်၊ code သည် ယခင် iteration ကိုမချန်ဘဲ main loop iteration သို့ ဝင်ရောက်သွားပါသည်။ အဆုံးမဲ့ loop နှင့် ပြန်ရေးသည်။ emscripten_sleepနှင့် mutexes ပြဿနာများရပ်တန့်သွားခဲ့သည်။ ကုဒ်သည် ပို၍ယုတ္တိရှိလာသည် - အမှန်မှာ၊ နောက်တစ်ခုက ကာတွန်းဘောင်ကို ပြင်ဆင်ပေးသည့် ကုဒ်အချို့ ကျွန်ုပ်တွင် မရှိပါ။ ပရိုဆက်ဆာသည် တစ်ခုခုကို တွက်ချက်ပြီး မျက်နှာပြင်ကို အချိန်နှင့်အမျှ အပ်ဒိတ်လုပ်နေပါသည်။ သို့သော်၊ ပြဿနာများသည် ထိုနေရာတွင် ရပ်မသွားဘဲ၊ တစ်ခါတစ်ရံ Qemu ကွပ်မျက်မှုသည် ခြွင်းချက် သို့မဟုတ် အမှားအယွင်းများမရှိဘဲ တိတ်တဆိတ် ရပ်တန့်သွားလိမ့်မည်။ အဲဒီအခိုက်အတန့်မှာ ကျွန်တော်လက်လျှော့လိုက်ပေမယ့် ရှေ့ကိုကြည့်လိုက်ရင် ပြဿနာက ဒီလိုပါ- coroutine code က တကယ်တော့ အသုံးမဝင်ပါဘူး။ setTimeout (သို့မဟုတ် အနည်းဆုံး သင်ထင်သလောက် မကြာခဏမဟုတ်ပါ) လုပ်ဆောင်ချက် emscripten_yield asynchronous call flag ကို ရိုးရိုးရှင်းရှင်း သတ်မှတ်သည်။ အချက်တစ်ခုလုံးက အဲဒါပါပဲ။ emscripten_coroutine_next ကွဲလွဲနေသောလုပ်ဆောင်ချက်မဟုတ်ပါ- အတွင်းတွင် ၎င်းသည် အလံကိုစစ်ဆေးသည်၊ ၎င်းကိုပြန်လည်သတ်မှတ်ပြီး လိုအပ်သည့်နေရာသို့ ထိန်းချုပ်မှုများကို လွှဲပြောင်းပေးသည်။ ဆိုလိုသည်မှာ၊ stack ၏မြှင့်တင်ရေးသည်ထိုတွင်အဆုံးသတ်သည်။ ပြဿနာမှာ ရှိပြီးသား coroutine backend မှ အရေးကြီးသောကုဒ်တစ်ခုကို ကော်ပီမကူးမိသောကြောင့် coroutine pool ကို disable လုပ်သောအခါတွင် ပေါ်လာသော use-after-free ကြောင့်၊ qemu_in_coroutine အမှန်က အမှန်အတိုင်း ပြန်ဖြစ်သွားသင့်တယ်။ ခေါ်ဆိုမှုဆီသို့ ဦးတည်ခဲ့သည်။ emscripten_yieldstack တွင်ဘယ်သူမှမရှိသောအထက် emscripten_coroutine_nextအစုအစည်းသည် အပေါ်ဆုံးသို့ ပြန့်သွားသော်လည်း မရှိပါ။ setTimeoutငါပြောခဲ့သလိုပဲ ကိုယ်လုပ်ခဲ့တာမဟုတ်ဘူး။

JavaScript ကုဒ်မျိုးဆက်

အမှန်မှာ၊ ဤနေရာတွင် “နုတ်ထားသောအသားကို ပြန်လှည့်” ရန် ကတိပြုထားသည်။ တကယ်မဟုတ်ဘူး။ ဟုတ်ပါတယ်၊ အကယ်၍ ကျွန်ုပ်တို့သည် browser တွင် Qemu နှင့် ၎င်းတွင် Node.js ကိုအသုံးပြုပါက၊ သဘာဝအားဖြင့်၊ Qemu တွင် ကုဒ်များထုတ်လုပ်ပြီးနောက် ကျွန်ုပ်တို့သည် JavaScript လုံးဝမှားယွင်းသွားမည်ဖြစ်သည်။ သို့သော် တစ်မျိုးတစ်ဖုံ ပြောင်းပြန် အသွင်ပြောင်းနေသေးသည်။

ပထမဦးစွာ Qemu အလုပ်လုပ်ပုံအကြောင်းအနည်းငယ်။ ချက်ချင်း ခွင့်လွှတ်ပါ- ကျွန်ုပ်သည် ပရော်ဖက်ရှင်နယ် Qemu developer မဟုတ်ပါ၊ ကျွန်ုပ်၏ ကောက်ချက်သည် အချို့နေရာများတွင် မှားယွင်းနိုင်ပါသည်။ သူတို့ပြောသလိုပဲ "ကျောင်းသားရဲ့ထင်မြင်ချက်ဟာ ဆရာရဲ့ထင်မြင်ယူဆချက်၊ Peano ရဲ့ axiomatics နဲ့ common sense နဲ့ တိုက်ဆိုင်နေစရာမလိုပါဘူး။" Qemu တွင် ပံ့ပိုးပေးထားသော ဧည့်သည်ဗိသုကာ အများအပြားရှိပြီး တစ်ခုစီအတွက် လမ်းညွှန်ကဲ့သို့ ရှိပါသည်။ target-i386. တည်ဆောက်သည့်အခါ၊ ဧည့်သည်ဗိသုကာများစွာအတွက် ပံ့ပိုးမှုကို သင်သတ်မှတ်နိုင်သော်လည်း ရလဒ်သည် များစွာသော binaries ဖြစ်လိမ့်မည်။ ဧည့်သည်ဗိသုကာကို ပံ့ပိုးရန် ကုဒ်သည် တစ်ဖန်၊ TCG (Tiny Code Generator) သည် အိမ်ရှင်ဗိသုကာအတွက် စက်ကုဒ်အဖြစ် ပြောင်းလဲပြီးသော အတွင်းပိုင်း Qemu လုပ်ဆောင်ချက်အချို့ကို ထုတ်ပေးသည်။ tcg directory တွင်ရှိသော readme ဖိုင်တွင်ဖော်ပြထားသည့်အတိုင်း၊ ၎င်းသည် မူလက ပုံမှန် C compiler ၏တစ်စိတ်တစ်ပိုင်းဖြစ်ပြီး နောက်ပိုင်းတွင် JIT အတွက် အဆင်ပြေအောင်ပြုလုပ်ထားသည်။ ထို့ကြောင့်၊ ဥပမာ၊ ဤစာတမ်း၏စည်းကမ်းချက်များအရ ပစ်မှတ်ဗိသုကာသည် ဧည့်သည်ဗိသုကာမဟုတ်တော့ဘဲ အိမ်ရှင်ဗိသုကာတစ်ခုဖြစ်သည်။ တစ်ချိန်ချိန်တွင်၊ တိကျသောအိမ်ရှင်ဗိသုကာတစ်ခုအတွက် code generator တစ်ခုမရှိပါက အခြားအစိတ်အပိုင်းတစ်ခုပေါ်လာသည် - Tiny Code Interpreter (TCI)၊ အမှန်မှာ၊ ၎င်း၏စာရွက်စာတမ်းတွင်ဖော်ပြထားသည့်အတိုင်း၊ ဤစကားပြန်သည် JIT ကုဒ်မီးစက်တစ်ခုအဖြစ် အမြဲတမ်းလုပ်ဆောင်နိုင်မည်မဟုတ်ပေ၊ အရေအတွက်အရသာမက အရှိန်အဟုန်ဖြင့်သာမက အရည်အသွေးလည်းကောင်းမွန်ပါသည်။ သူ့ဖော်ပြချက်နဲ့ လုံးဝသက်ဆိုင်တယ်လို့ ကျွန်တော်သေချာမသိပေမယ့်။

အစပိုင်းတွင် ကျွန်ုပ်သည် ပြည့်စုံသော TCG နောက်ခံကို ဖန်တီးရန် ကြိုးစားခဲ့သော်လည်း အရင်းအမြစ်ကုဒ်နှင့် bytecode လမ်းညွှန်ချက်များကို လုံးလုံးလျားလျား ရှင်းလင်းခြင်းမရှိသည့်အတွက် လျင်မြန်စွာ ရှုပ်ထွေးသွားသောကြောင့် TCI စကားပြန်ကို ခြုံငုံမိရန် ဆုံးဖြတ်ခဲ့သည်။ ၎င်းသည် အားသာချက်များစွာကို ပေးဆောင်သည်-

  • code generator ကို အကောင်အထည်ဖော်သောအခါတွင်၊ သင်သည် ညွှန်ကြားချက်များ၏ ဖော်ပြချက်ကို မကြည့်ဘဲ စကားပြန်ကုဒ်တွင် ကြည့်နိုင်သည်။
  • သင်ကြုံတွေ့ရသော ဘာသာပြန်ဘလောက်တိုင်းအတွက်မဟုတ်ဘဲ၊ ဥပမာအားဖြင့် ရာနှင့်ချီလုပ်ဆောင်ပြီးမှသာ လုပ်ဆောင်ချက်များကို ဖန်တီးနိုင်သည်။
  • ထုတ်လုပ်လိုက်သောကုဒ်သည် ပြောင်းလဲပါက (၎င်းသည် ဖြစ်နိုင်ချေရှိပုံရသည်၊ စကားလုံး patch ပါရှိသော အမည်များဖြင့် လုပ်ဆောင်ချက်များကို ကြည့်ပါက) ကျွန်ုပ်သည် ထုတ်လုပ်လိုက်သော JS ကုဒ်ကို တရားဝင်အောင်ဖျက်ရန် လိုအပ်ပေလိမ့်မည်၊ သို့သော် အနည်းဆုံး ကျွန်ုပ်မှ ၎င်းကို ပြန်လည်ထုတ်ပေးရန် တစ်ခုခုတော့ ရှိပါမည်။

တတိယအချက်နှင့်ပတ်သက်၍၊ ကုဒ်ကိုပထမဆုံးအကြိမ်လုပ်ဆောင်ပြီးနောက် ဖာထေးခြင်းဖြစ်နိုင်သည်ကို ကျွန်ုပ်မသေချာသော်လည်း ပထမအချက်နှစ်ချက်သည် လုံလောက်ပါသည်။

အစပိုင်းတွင်၊ မူရင်း bytecode ညွှန်ကြားချက်၏လိပ်စာတွင် ကုဒ်ကို ကြီးမားသောခလုတ်ပုံစံဖြင့် ထုတ်လုပ်ခဲ့သော်လည်း၊ ထို့နောက်တွင် Emscripten အကြောင်း ဆောင်းပါးကို သတိရခြင်း၊ ထုတ်လုပ်ထားသော JS ကို ပိုမိုကောင်းမွန်အောင်ပြုလုပ်ခြင်းနှင့် ပြန်လှည့်ခြင်းအတွက်၊ အထူးသဖြင့် ၎င်းကို မျက်မြင်ကိုယ်တွေ့ဖြစ်သောကြောင့် လူသားကုဒ်ပိုမိုထုတ်လုပ်ရန် ဆုံးဖြတ်ခဲ့သည်။ ဘာသာပြန်သည်။ ခဏအကြာတွင် ifs ဖြင့် ကုဒ်ထုတ်ပေးသည့် ကုဒ်ထုတ်ပေးသည့် ဂျင်နရေတာတစ်ခု ပြီးသည်ထက် စောသည်ထက် စော၍ ပြီးသည် ဟု မပြောပါ။ ဒါပေမယ့် ကံဆိုးစွာနဲ့ပဲ လမ်းညွှန်ချက်တွေဟာ အရှည်မမှန်ကန်ကြောင်း မက်ဆေ့ချ်ပေးရင်း ပျက်ကျသွားပါတယ်။ ထို့အပြင်၊ ဤ recursion အဆင့်တွင်နောက်ဆုံးညွှန်ကြားချက်ဖြစ်သည်။ brcond. ကောင်းပြီ၊ ထပ်ခါတလဲလဲခေါ်ဆိုခြင်းမပြုမီနှင့် ခေါ်ဆိုပြီးနောက် ဤညွှန်ကြားချက်၏မျိုးဆက်တွင် ထပ်တူထပ်မျှစစ်ဆေးချက်တစ်ခုကို ပေါင်းထည့်လိုက်မည်ဖြစ်ပြီး... ၎င်းတို့ထဲမှ တစ်ခုမျှ လုပ်ဆောင်ခြင်းမရှိသော်လည်း အတည်ပြုခလုတ်ပြီးနောက် ၎င်းတို့ မအောင်မြင်သေးပါ။ အဆုံးတွင်၊ ထုတ်လုပ်ထားသောကုဒ်ကိုလေ့လာပြီးနောက်၊ switch ပြီးနောက်၊ လက်ရှိညွှန်ကြားချက်ဆီသို့ညွှန်ပြချက်ကို stack မှပြန်လည်စတင်ပြီးထုတ်လုပ်ထားသော JavaScript ကုဒ်ဖြင့် overwrite ဖြစ်ကောင်းဖြစ်နိုင်သည်ကိုငါနားလည်ခဲ့သည်။ ဒီလိုနဲ့ ထွက်လာတယ်။ ကြားခံကို တစ်မီဂါဘိုက်မှ ဆယ်ခုအထိ တိုးလာခြင်းသည် ဘာကိုမှ မဖြစ်ပေါ်စေဘဲ၊ ကုဒ်ဂျင်နရေတာသည် စက်ဝိုင်းအတွင်းလည်ပတ်နေကြောင်း ထင်ရှားလာသည်။ ကျွန်ုပ်တို့သည် လက်ရှိ တီဘီရောဂါ၏ နယ်နိမိတ်များကို ကျော်လွန်မသွားကြောင်း စစ်ဆေးရန် လိုအပ်ပြီး အကယ်၍ ကျွန်ုပ်တို့ ဆက်လက်လုပ်ဆောင်နိုင်စေရန်အတွက် နောက်ထပ် တီဘီရောဂါ၏ လိပ်စာကို အနုတ်လက္ခဏာဖြင့် ထုတ်ပေးပါ။ ထို့အပြင်၊ ၎င်းသည် "ဤ bytecode အပိုင်းကိုပြောင်းလဲသွားပါက၊ ထုတ်လုပ်လိုက်သောလုပ်ဆောင်ချက်များကို ပျက်ပြားစေသင့်သည်" ဟူသော ပြဿနာကို ဖြေရှင်းပေးပါသည်။ — ဤဘာသာပြန်ဘလောက်နှင့် သက်ဆိုင်သည့် လုပ်ဆောင်ချက်ကိုသာ ဖျက်ပစ်ရန် လိုအပ်သည်။ စကားမစပ်၊ ကျွန်ုပ်သည် Chromium တွင် အရာအားလုံးကို အမှားပြင်ပြီးသော်လည်း (ကျွန်တော် Firefox ကိုသုံး၍ စမ်းသပ်မှုများအတွက် သီးခြားဘရောက်ဆာကို အသုံးပြုရန် ပိုမိုလွယ်ကူသော်လည်း၊) Firefox သည် asm.js စံနှုန်းနှင့် ကိုက်ညီမှုမရှိခြင်းကို ပြုပြင်ပေးကာ ကုဒ်သည် ပိုမိုမြန်ဆန်စွာ အလုပ်လုပ်လာပါသည်။ ခရိုမီယမ်။

ထုတ်ပေးသောကုဒ်နမူနာ

Compiling 0x15b46d0:
CompiledTB[0x015b46d0] = function(stdlib, ffi, heap) {
"use asm";
var HEAP8 = new stdlib.Int8Array(heap);
var HEAP16 = new stdlib.Int16Array(heap);
var HEAP32 = new stdlib.Int32Array(heap);
var HEAPU8 = new stdlib.Uint8Array(heap);
var HEAPU16 = new stdlib.Uint16Array(heap);
var HEAPU32 = new stdlib.Uint32Array(heap);

var dynCall_iiiiiiiiiii = ffi.dynCall_iiiiiiiiiii;
var getTempRet0 = ffi.getTempRet0;
var badAlignment = ffi.badAlignment;
var _i64Add = ffi._i64Add;
var _i64Subtract = ffi._i64Subtract;
var Math_imul = ffi.Math_imul;
var _mul_unsigned_long_long = ffi._mul_unsigned_long_long;
var execute_if_compiled = ffi.execute_if_compiled;
var getThrew = ffi.getThrew;
var abort = ffi.abort;
var qemu_ld_ub = ffi.qemu_ld_ub;
var qemu_ld_leuw = ffi.qemu_ld_leuw;
var qemu_ld_leul = ffi.qemu_ld_leul;
var qemu_ld_beuw = ffi.qemu_ld_beuw;
var qemu_ld_beul = ffi.qemu_ld_beul;
var qemu_ld_beq = ffi.qemu_ld_beq;
var qemu_ld_leq = ffi.qemu_ld_leq;
var qemu_st_b = ffi.qemu_st_b;
var qemu_st_lew = ffi.qemu_st_lew;
var qemu_st_lel = ffi.qemu_st_lel;
var qemu_st_bew = ffi.qemu_st_bew;
var qemu_st_bel = ffi.qemu_st_bel;
var qemu_st_leq = ffi.qemu_st_leq;
var qemu_st_beq = ffi.qemu_st_beq;

function tb_fun(tb_ptr, env, sp_value, depth) {
  tb_ptr = tb_ptr|0;
  env = env|0;
  sp_value = sp_value|0;
  depth = depth|0;
  var u0 = 0, u1 = 0, u2 = 0, u3 = 0, result = 0;
  var r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0;
  var r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0, r16 = 0, r17 = 0, r18 = 0, r19 = 0;
  var r20 = 0, r21 = 0, r22 = 0, r23 = 0, r24 = 0, r25 = 0, r26 = 0, r27 = 0, r28 = 0, r29 = 0;
  var r30 = 0, r31 = 0, r41 = 0, r42 = 0, r43 = 0, r44 = 0;
    r14 = env|0;
    r15 = sp_value|0;
  START: do {
    r0 = HEAPU32[((r14 + (-4))|0) >> 2] | 0;
    r42 = 0;
    result = ((r0|0) != (r42|0))|0;
    HEAPU32[1445307] = r0;
    HEAPU32[1445321] = r14;
    if(result|0) {
    HEAPU32[1445322] = r15;
    return 0x0345bf93|0;
    }
    r0 = HEAPU32[((r14 + (16))|0) >> 2] | 0;
    r42 = 8;
    r0 = ((r0|0) - (r42|0))|0;
    HEAPU32[(r14 + (16)) >> 2] = r0;
    r1 = 8;
    HEAPU32[(r14 + (44)) >> 2] = r1;
    r1 = r0|0;
    HEAPU32[(r14 + (40)) >> 2] = r1;
    r42 = 4;
    r0 = ((r0|0) + (r42|0))|0;
    r2 = HEAPU32[((r14 + (24))|0) >> 2] | 0;
    HEAPU32[1445307] = r0;
    HEAPU32[1445308] = r1;
    HEAPU32[1445309] = r2;
    HEAPU32[1445321] = r14;
    HEAPU32[1445322] = r15;
    qemu_st_lel(env|0, r0|0, r2|0, 34, 22759218);
if(getThrew() | 0) abort();
    r0 = 3241038392;
    HEAPU32[1445307] = r0;
    r0 = qemu_ld_leul(env|0, r0|0, 34, 22759233)|0;
if(getThrew() | 0) abort();
    HEAPU32[(r14 + (24)) >> 2] = r0;
    r1 = HEAPU32[((r14 + (12))|0) >> 2] | 0;
    r2 = HEAPU32[((r14 + (40))|0) >> 2] | 0;
    HEAPU32[1445307] = r0;
    HEAPU32[1445308] = r1;
    HEAPU32[1445309] = r2;
    qemu_st_lel(env|0, r2|0, r1|0, 34, 22759265);
if(getThrew() | 0) abort();
    r0 = HEAPU32[((r14 + (24))|0) >> 2] | 0;
    HEAPU32[(r14 + (40)) >> 2] = r0;
    r1 = 24;
    HEAPU32[(r14 + (52)) >> 2] = r1;
    r42 = 0;
    result = ((r0|0) == (r42|0))|0;
    if(result|0) {
    HEAPU32[1445307] = r0;
    HEAPU32[1445308] = r1;
    }
    HEAPU32[1445307] = r0;
    HEAPU32[1445308] = r1;
    return execute_if_compiled(22759392|0, env|0, sp_value|0, depth|0) | 0;
    return execute_if_compiled(23164080|0, env|0, sp_value|0, depth|0) | 0;
    break;
  } while(1); abort(); return 0|0;
}
return {tb_fun: tb_fun};
}(window, CompilerFFI, Module.buffer)["tb_fun"]

ကောက်ချက်

ဒါကြောင့် အလုပ်ကမပြီးသေးပေမယ့် ဒီရေရှည်တည်ဆောက်မှုကို ပြီးပြည့်စုံအောင် တိတ်တဆိတ်ယူလာရတာ ငြီးငွေ့နေတယ်။ ထို့ကြောင့် ကျွန်ုပ်သည် ယခုအချိန်တွင် ထုတ်ဝေရန် ဆုံးဖြတ်လိုက်သည်။ ကုဒ်သည် နေရာများတွင် အနည်းငယ်ကြောက်စရာကောင်းသည်၊ အကြောင်းမှာ၊ ဤအရာသည် စမ်းသပ်မှုတစ်ခုဖြစ်ပြီး မည်သည့်အရာလုပ်ဆောင်ရမည်ကို ကြိုတင်ရှင်းလင်းစွာ မသိရသေးသောကြောင့်ဖြစ်သည်။ ဖြစ်နိုင်သည်၊ ထို့နောက် Qemu ၏ နောက်ထပ်ခေတ်မီဗားရှင်းအချို့၏ထိပ်တွင် ပုံမှန်အနုမြူဗုံးများကို ထုတ်ပေးသင့်သည်။ ဤအတောအတွင်း၊ Gita တွင် ဘလော့ဂ်ဖော်မတ်ဖြင့် စာတွဲတစ်ခု ရှိသည်- အနည်းဆုံး တစ်နည်းနည်းဖြင့် ကျော်သွားသော "အဆင့်" တစ်ခုစီအတွက်၊ ရုရှားဘာသာစကားဖြင့် အသေးစိတ် မှတ်ချက်တစ်ခုကို ထည့်သွင်းထားသည်။ တကယ်တော့ ဒီဆောင်းပါးဟာ နိဂုံးချုပ်ချက်ကို အကျယ်တဝင့် ပြန်ပြောပြတာပါ။ git log.

အားလုံးကြိုးစားနိုင်ပါတယ်။ ဒီမှာ (အသွားအလာ သတိပြုပါ။)

ဘာတွေလုပ်ဆောင်နေပြီလဲ-

  • x86 ပရိုဆက်ဆာ လည်ပတ်နေသည်။
  • စက်ကုဒ်မှ JavaScript သို့ JIT ကုဒ်ဂျင်နရေတာ၏ ရှေ့ပြေးပုံစံတစ်ခုရှိသည်။
  • အခြား 32-bit ဧည့်သည်ဗိသုကာများကို စုစည်းရန်အတွက် ပုံစံပလိတ်တစ်ခု ရှိသည်- ယခုဖွင့်သည့်အဆင့်တွင် ဘရောက်ဆာတွင် MIPS ဗိသုကာအေးခဲမှုအတွက် Linux ကို သင်နှစ်သက်နိုင်သည်

တခြားဘာလုပ်နိုင်မလဲ။

  • အတုယူမှုကို အရှိန်မြှင့်ပါ။ JIT မုဒ်တွင်ပင် Virtual x86 ထက် နှေးကွေးနေပုံရသည် (သို့သော် အတုယူ ဟာ့ဒ်ဝဲနှင့် ဗိသုကာလက်ရာများစွာပါရှိသော Qemu တစ်ခုလုံး ဖြစ်နိုင်ချေရှိသည်)
  • သာမာန်အင်တာဖေ့စ်တစ်ခုပြုလုပ်ရန် - ပွင့်ပွင့်လင်းလင်းပြောရလျှင်၊ ကျွန်ုပ်သည် ဝဘ်ဆော့ဖ်ဝဲကောင်းတစ်ဦးမဟုတ်ပါ၊ ထို့ကြောင့် ယခုအချိန်တွင် ကျွန်ုပ်သည် တတ်နိုင်သမျှ စံ Emscripten shell ကို ပြန်လည်ဖန်တီးထားပါသည်။
  • ပိုမိုရှုပ်ထွေးသော Qemu လုပ်ဆောင်ချက်များကို စတင်ရန် ကြိုးစားပါ - ကွန်ရက်ချိတ်ဆက်ခြင်း၊ VM ရွှေ့ပြောင်းခြင်း စသည်ဖြင့်။
  • UPD: ယခင် Qemu နှင့် အခြားပရောဂျက်များ၏ ပေါ်တာဆွဲခြင်းများ ပြုလုပ်ခဲ့သည့်အတိုင်း သင်၏တိုးတက်မှုအနည်းငယ်နှင့် ချို့ယွင်းချက်အစီရင်ခံစာများကို Emscripten အထက်ပိုင်းသို့ တင်ပြရန် လိုအပ်မည်ဖြစ်ပါသည်။ ကျွန်ုပ်၏လုပ်ငန်းတာဝန်တစ်စိတ်တစ်ပိုင်းအနေဖြင့် Emscripten အား ၎င်းတို့၏ပံ့ပိုးကူညီမှုများကို သွယ်ဝိုက်စွာအသုံးပြုနိုင်သည့်အတွက် ကျေးဇူးတင်ပါသည်။

source: www.habr.com

မှတ်ချက် Add