Tim emulator x86 menemukan kode yang terlalu buruk sampai mereka memperbaikinya saat emulasi
(devblogs.microsoft.com)- Emulator x86-32 menghasilkan kode native melalui translasi biner untuk menjalankan kode x86-32 di prosesor lain, dan memberikan peningkatan performa besar dibanding pendekatan interpreter
- Emulator tersebut dapat dipahami sebagai melihat x86-32 seperti bytecode, dengan struktur yang membuat emulator bekerja layaknya kompiler JIT
- Sebuah program perlu mengalokasikan sekitar 64KB memori di stack dan menginisialisasinya; cara umumnya adalah melakukan stack probe, lalu menurunkan stack pointer dan menginisialisasi memori dengan loop kecil
- Kompiler untuk kode itu, alih-alih membuat loop, menghasilkan 65.536 instruksi penulisan byte terpisah, dan karena tiap instruksi berukuran 4 byte, diperlukan 256KB kode untuk menginisialisasi data 64KB
- Tim emulator menambahkan kode khusus ke translator untuk mendeteksi fungsi ini dan menggantinya dengan loop pendek yang setara
Latar belakang: emulator x86-32 dan translasi biner
- Windows pernah menyertakan emulator prosesor x86-32 untuk sistem yang berjalan di prosesor selain x86-32
- Tulisan aslinya tidak menyebutkan prosesor mana yang menjadi kasus ini
- Emulator tersebut menggunakan translasi biner untuk menghasilkan kode native yang menjalankan perilaku yang setara dengan kode x86-32 asli
- Pendekatan ini memberikan peningkatan performa yang signifikan dibanding emulasi berbasis interpreter
- Ini bisa dipahami dengan melihat x86-32 sebagai bytecode, dan emulator sebagai kompiler JIT
Kode bermasalah: inisialisasi memori stack 64KB
- Sebuah program perlu mengalokasikan sekitar 64KB memori di stack dan menginisialisasinya
- Cara standarnya adalah terlebih dahulu melakukan stack probe untuk memastikan 64KB memori itu dapat digunakan
- Setelah itu, stack pointer dikurangi sebesar 65.536, lalu memori diinisialisasi menggunakan loop kecil yang rapat
Loop unrolling kompiler yang berlebihan
- Kompiler yang mengompilasi kode tersebut tidak menghasilkan loop untuk menginisialisasi setiap byte
- Sebagai gantinya, loop itu dibentangkan menjadi 65.536 instruksi “tulis byte ke memori” yang terpisah
- Setiap instruksi panjangnya 4 byte
- Akibatnya, untuk menginisialisasi data 64KB dibutuhkan kode 256KB
Respons tim emulator
- Tim emulator menambahkan kode khusus ke translator untuk mendeteksi fungsi ini
- Fungsi yang terdeteksi kemudian diganti dengan loop pendek yang menjalankan perilaku setara
- Penanganan ini tidak sekadar menerjemahkan kode program asli apa adanya, tetapi mengubah pola kode yang tidak efisien menjadi bentuk yang lebih ringkas selama emulasi
1 komentar
Pendapat di Lobste.rs
Saya cukup suka komentar yang menjelaskan loop unrolling kepada Raymond Chen
Di antara orang-orang yang membaca tulisan seperti ini, tidak semuanya sudah tahu seluruh pengetahuan latar belakang, jadi banyak juga yang berterima kasih atas petunjuk untuk belajar lebih jauh
https://joelonsoftware.com/2004/06/…
Sepertinya ini terjadi di Alpha. Soalnya, sangat banyak pekerjaan yang dimasukkan ke emulator x86 untuk platform itu