Hai kawan!
Memiliki aplikasi yang sangat sederhana, yang memanggil metode antarmuka seperti ini.
namespace InterfaceCalls
{
public interface IFoo
{
int Bar();
}
class Program
{
public static int M1(IFoo foo)
{
return foo.Bar();
}
static void Main(string[] args)
{
M1(null);
}
}
}
Itu menghasilkan ASM berikut untuk 2.2 (untuk 3.0 ada lea rsp,[rbp] alih-alih menambahkan rsp,30h)
return foo.Bar();
00007FFE7B521846 mov rcx,rsi
00007FFE7B521849 mov r11,7FFE7B410028h
00007FFE7B521853 cmp dword ptr [rcx],ecx
00007FFE7B521855 call qword ptr [7FFE7B410028h]
00007FFE7B52185B nop
00007FFE7B52185C add rsp,30h
00007FFE7B521860 pop rsi
00007FFE7B521861 ret
Maaf untuk pertanyaan yang berpotensi sangat bodoh dan pemula :) tetapi bisakah seseorang memberi saya petunjuk tentang:
1 Mengapa kita membutuhkan instruksi cmp di sini (tidak ada lompatan bersyarat setelah cmp)
2 Apa itu 7FFE7B410028h dan mengapa kami memuat r11 di sini
3 Bukankah terlalu mahal untuk memiliki cmp per panggilan antarmuka (dapatkah cml dalam hal ini menyebabkan prediksi cabang meleset?)
Terima kasih banyak!
CMP adalah pemeriksaan nulll awal.
Anda dapat membaca tentang pengiriman antarmuka di sini https://github.com/dotnet/coreclr/blob/master/Documentation/botr/virtual-stub-dispatch.md
Mengapa kita membutuhkan instruksi cmp di sini (tidak ada lompatan bersyarat setelah cmp)
Untuk memicu NullReferenceException
pada titik panggilan ketika this
adalah null
.
Apa itu 7FFE7B410028h dan mengapa kami memuat di r11 di sini
Alamat "sel indirection" yang menunjuk ke sebuah rintisan yang menyelesaikan dan memanggil metode implementasi antarmuka. Sayangnya menyelesaikan metode antarmuka adalah operasi yang relatif rumit yang tidak dapat dilakukan "inline".
Awalnya menunjuk ke https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/coreclr/src/vm/amd64/VirtualCallStubAMD64.asm#L28
Beberapa dokumentasi tersedia di sini (walaupun saya tidak yakin seberapa mutakhirnya)
https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md
Anda mungkin dapat langsung membuka https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md#stubs untuk mendapatkan gambaran umum singkat.
Bukankah terlalu mahal untuk memiliki cmp per panggilan antarmuka (dapatkah cml dalam hal ini menyebabkan prediksi cabang meleset?)
Ini adalah instruksi perbandingan, bukan instruksi cabang bersyarat, jadi tidak ada hubungannya dengan prediksi cabang. Dan itu sangat murah dibandingkan dengan biaya panggilan antarmuka yang sebenarnya.
@mikedn @omariom Terima kasih
Komentar yang paling membantu
Untuk memicu
NullReferenceException
pada titik panggilan ketikathis
adalahnull
.Alamat "sel indirection" yang menunjuk ke sebuah rintisan yang menyelesaikan dan memanggil metode implementasi antarmuka. Sayangnya menyelesaikan metode antarmuka adalah operasi yang relatif rumit yang tidak dapat dilakukan "inline".
Awalnya menunjuk ke https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/coreclr/src/vm/amd64/VirtualCallStubAMD64.asm#L28
Beberapa dokumentasi tersedia di sini (walaupun saya tidak yakin seberapa mutakhirnya)
https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md
Anda mungkin dapat langsung membuka https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md#stubs untuk mendapatkan gambaran umum singkat.
Ini adalah instruksi perbandingan, bukan instruksi cabang bersyarat, jadi tidak ada hubungannya dengan prediksi cabang. Dan itu sangat murah dibandingkan dengan biaya panggilan antarmuka yang sebenarnya.