MethodImplOptions.InternalCall
Itu berarti bahwa metode ini benar-benar diimplementasikan dalam CLR, ditulis dalam C ++. Kompilator just-in-time berkonsultasi dengan tabel dengan metode yang diimplementasikan secara internal dan mengkompilasi panggilan ke fungsi C ++ secara langsung.
Melihat kode membutuhkan kode sumber untuk CLR. Anda bisa mendapatkannya dari distribusi SSCLI20 . Itu ditulis di sekitar kerangka waktu. NET 2.0, saya telah menemukan implementasi tingkat rendah, ingin Math.Pow()
tetap sebagian besar akurat untuk versi CLR nanti.
Tabel pencarian terletak di clr / src / vm / ecall.cpp. Bagian yang relevan dengan Math.Pow()
terlihat seperti ini:
FCFuncStart(gMathFuncs)
FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
FCFuncElement("Exp", COMDouble::Exp)
FCFuncElement("Pow", COMDouble::Pow)
// etc..
FCFuncEnd()
Mencari "COMDouble" akan membawa Anda ke clr / src / classlibnative / float / comfloat.cpp. Saya akan menghindarkan Anda kodenya, lihat saja sendiri. Ini pada dasarnya memeriksa kasus sudut, lalu memanggil versi CRT untuk pow()
.
Satu-satunya detail implementasi lain yang menarik adalah makro FCIntrinsic dalam tabel. Itu petunjuk bahwa jitter dapat mengimplementasikan fungsi sebagai intrinsik. Dengan kata lain, gantilah panggilan fungsi dengan instruksi kode mesin titik mengambang. Yang tidak demikian halnya Pow()
, tidak ada instruksi FPU untuk itu. Namun yang pasti untuk operasi sederhana lainnya. Yang perlu dicatat adalah bahwa ini dapat membuat matematika floating point dalam C # secara substansial lebih cepat daripada kode yang sama dalam C ++, periksa jawaban ini untuk alasan mengapa.
Omong-omong, kode sumber untuk CRT juga tersedia jika Anda memiliki versi lengkap dari direktori Visual Studio vc / crt / src. Namun, Anda akan menabrak tembok pow()
, Microsoft membeli kode itu dari Intel. Melakukan pekerjaan yang lebih baik daripada para insinyur Intel tidak mungkin. Meskipun identitas buku sekolah menengah saya dua kali lebih cepat ketika saya mencobanya:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
Tapi bukan pengganti yang benar karena mengakumulasi kesalahan dari 3 operasi floating point dan tidak berurusan dengan masalah domain aneh yang dimiliki Pow (). Seperti 0 ^ 0 dan -Infinity dinaikkan ke daya apa pun.
InternalCall
denganextern
pengubah (karena mereka tampaknya saling bertentangan), silakan lihat pertanyaan (dan jawaban yang dihasilkan) yang saya posting tentang hal yang sama.