Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
あなたとJIT, 今すぐアセンブ ル
Search
monochrome
August 09, 2025
Programming
1.1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
あなたとJIT, 今すぐアセンブ ル
Kernel/VM探検隊@東京No18
monochrome
August 09, 2025
More Decks by monochrome
See All by monochrome
RubyKaigi2026: Invariants in my own Ruby
sisshiki1969
0
40
Improving my own Ruby thereafter
sisshiki1969
1
270
Improve my own Ruby
sisshiki1969
1
630
My own Ruby, thereafter
sisshiki1969
0
430
Running Optcarrot (faster) on my own Ruby.
sisshiki1969
1
350
仮想マシンにおけるスタックの管理
sisshiki1969
0
260
Rustでゴミ集め
sisshiki1969
1
390
RustでつくるRubyのFiber
sisshiki1969
0
340
Shinjuku.rs#15 Rustでつくるx86アセンブラ
sisshiki1969
0
1.8k
Other Decks in Programming
See All in Programming
Spec-driven Development with AI
simas
PRO
0
2.2k
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
1.6k
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
4.9k
Railsバージョンを4倍にした話
optim
0
840
Crash Auto Pipelines
veronikapj
1
180
Spec-Driven Development - Why Vaadin Is the Perfect Fit
simas
PRO
0
190
R8 の設定見直しでアプリサイズ削減
andpad
0
240
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
630
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
1.1k
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
140
JIS keyboard support in Omarchy
lef237
0
170
Materialが消えた日 〜真っ白なFlutterキャンバスにRenderObjectで絵を描く〜
umigishiaoi
0
120
Featured
See All Featured
Producing Creativity
orderedlist
PRO
348
41k
30 Presentation Tips
portentint
PRO
1
450
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.7k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.5k
Evolving SEO for Evolving Search Engines
ryanjones
0
340
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Color Theory Basics | Prateek | Gurzu
gurzu
1
510
The Mindset for Success: Future Career Progression
greggifford
PRO
0
550
GraphQLとの向き合い方2022年版
quramy
50
15k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
420
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Transcript
あなたとJITASM, 今すぐアセンブ ル @s_isshiki1969 sisshiki1969 monochrome JIT
アセンブラ is 何 int main() { return 42; } main:
push rbp mov rbp, rsp mov eax, 42 pop rbp ret 55 48 89 e5 b8 2a 00 00 00 5d c3 0f 1f 00 hoge.c hoge.s hoge.o これ アセンブリのテキストファイルを機械語へ変換
ダイナミックアセンブラ • 「実行時に機械語を吐くプログラム」のためのライブラリ • メモリ上に機械語を格納するバッファを確保し、そこへ機械語を生成して いく • 応用例としてはJITコンパイラなど • 例:Xbyak(C++、テンプレート)
DynASM(C、プリプロセッサ) monoasm(Rust、手続きマクロ)
monoasm • https://github.com/sisshiki1969/monoasm • Rustで書かれたx86-64専用ダイナミック・アセンブラ • ①ランタイム ②マクロ定義 で構成 • Rubyの自作JITコンパイラ(monoruby)のために開発 ◦
RubyKaigi 2024, 2025で発表 • mov・四則演算・論理演算・比較・条件分岐・浮動小数点数演算 • SIMD命令群は未対応
手続きマクロ(proc macro) マクロの中身をRustコードへ変換するRustプログラム #[proc_macro] pub fn monoasm(tokens: TokenStream) -> TokenStream
{ let stmts = parse_macro_input!(tokens as inst::Stmts); let base = stmts.base; let mut ts = quote!(let mut jit = #base;); ts.extend(stmts.contents.into_iter().map(compile)); quote!({ #ts }).into() } monoasm!(&mut jit, movq rax, [rdi + rsi * 8 + 16]; ); jit.enc_rexw_mr( &[0x8b], Reg::from(0), Rm::ind( Reg::from(7), Disp::from_disp(16), Scale::S1(3, Reg::from(6)), ), );
コード生成:インタプリタ monoasm! { &mut self.jit, movq r15, (self.dispatch.as_ptr()); movzxb rax,
[r13 + (OPECODE)]; addq r13, 16; jmp [r15 + rax * 8]; }; r13: PC(現在処理中のバイトコードを指す) self.dispatch: ジャンプテーブルの先頭アドレス
コード生成:JITコンパイラ match kind { BinOpK::Add => { let overflow =
self.jit.label(); match mode { OpMode::RR(_, _) => { monoasm!( &mut self.jit, subq R(lhs_r), 1; addq R(lhs_r), R(rhs_r); jo overflow; ); } OpMode::RI(_, i) | OpMode::IR(i, _) => { monoasm!( &mut self.jit, addq R(lhs_r), ((*i as i64) << 1); jo overflow; ); } } self.jit.select_page(1); monoasm!( &mut self.jit, overflow: movq rdi, (Value::symbol("_arith_overflow").id()); jmp deopt; ); self.jit.select_page(0); 複数のコードページを使い分ける
コード生成 match kind { BinOpK::Add => { let overflow =
self.jit.label(); match mode { OpMode::RR(_, _) => { monoasm!( &mut self.jit, subq R(lhs_r), 1; addq R(lhs_r), R(rhs_r); jo overflow; ); } OpMode::RI(_, i) | OpMode::IR(i, _) => { monoasm!( &mut self.jit, addq R(lhs_r), ((*i as i64) << 1); jo overflow; ); } } self.jit.select_page(1); monoasm!( &mut self.jit, overflow: movq rdi, (Value::symbol("_arith_overflow").id()); jmp deopt; ); self.jit.select_page(0); ラベルを定義 ラベルを使用 ラベルを実アドレスにバインド let mask = 0x8000_0000_0000_0000u64 as i64; let imm = self.jit.const_i64(mask); monoasm!( &mut self.jit, xorps xmm(dst), [rip + imm]; ); データ領域にPC相対アクセス ()内にRustの式を書ける
Array#size fn array_size(bb: &mut BBContext, ir: &mut AsmIr, _: &JitContext,
_: &Store, callsite: &CallSiteInfo, _: ClassId) -> bool { if !callsite.is_simple() { return false; } let dst = callsite.dst; ir.inline(move |gen, _, _| { monoasm! { &mut gen.jit, movq rax, [rdi + (RVALUE_OFFSET_ARY_CAPA)]; cmpq rax, (ARRAY_INLINE_CAPA); cmovgtq rax, [rdi + (RVALUE_OFFSET_HEAP_LEN)]; salq rax, 1; orq rax, 1; } }); bb.reg2acc_fixnum(ir, GP::Rax, dst); true }
Array#size monoasm! { &mut gen.jit, movq rax, [rdi + (RVALUE_OFFSET_ARY_CAPA)];
cmpq rax, (ARRAY_INLINE_CAPA); cmovgtq rax, [rdi + (RVALUE_OFFSET_HEAP_LEN)]; salq rax, 1; orq rax, 1; } [0] [1] [2] [3] [4] Capa <= 5 Capa Ptr Capa > 5 [0] [1] [2] ... [Len-1] Array object Array object Capa Len
Math#sqrt fn math_sqrt(bb: &mut BBContext, ir: &mut AsmIr, _: &JitContext,
_: &Store, callsite: &CallSiteInfo, _: ClassId) -> bool { if !callsite.is_simple() { return false; } let CallSiteInfo { args, dst, .. } = *callsite; let deopt = ir.new_deopt(bb); let fsrc = bb.fetch_float_for_xmm(ir, args, deopt).enc(); if let Some(dst) = dst { let fret = bb.xmm_write_enc(dst); ir.inline(move |gen, _, _| { monoasm!( &mut gen.jit, sqrtsd xmm(fret), xmm(fsrc); ); }); } true }
JavaScript from “Building a baseline JIT for Lua automatically”, Blog
of Haoran Xu Maglev
Python • PEP 659 – Specializing Adaptive Interpreter • PEP
744 – JIT Compilation • Copy-and-patch compilation: a fast compilation algorithm for high-level languages and bytecode adaptive interpreter Baseline JIT tier-up deopt Interpreter specialize
Ruby • YJIT (Lazy Basic Block Versioning) • ZJIT •
monoruby (https://github.com/sisshiki1969/monoruby) Interpreter Optimizing JIT tier-up deopt
Optcarrot benchmark (~3000 frame)
目的:機械語を書く 手段:コンパイラを書く あなたとJITASM, 今すぐアセンブ ル