日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CLR运行时细节 - Method Descriptor

發布時間:2023/12/4 编程问答 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CLR运行时细节 - Method Descriptor 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

方法描述符:MethodDesc

  • 運行時用來描述類型的托管方法,它保存在方法描述桶(MethodDescChunk)內;

  • 方法描述符保存了方法在運行時的一些重要信息:

    • 是否JIT編譯;

    • 是否有方法表槽(決定了方法入口是跟在方法描述符(MethodDesc)后還是在方法表(MethodTable)后面);

    • 距離MethodDescChunk的索引(chunkIndex);

    • Token的末位(這個在編譯期確定了);

    • 方法的一些標識比如是否靜態 非內聯等;

    • 方法表槽(slot number);

    • 以及最重要的方法入口(entrypoint);

官方的描述:
MethodDesc (method descriptor) is the internal representation of a managed method. It serves several purposes:

  • Provides a unique method handle, usable throughout the runtime. For normal methods, the MethodDesc is a unique handle for a triplet.

  • Caches frequently used information that is expensive to compute from metadata (e.g. whether the method is static).

  • Captures the runtime state of the method (e.g. whether the code has been generated for the method already).

  • Owns the entry point of the method.

先看下Demo C# MethodDesc.cs 代碼:



using System;

using System.Runtime.CompilerServices;

public class Program

{

public static void Main(string[] args)

{

Console.WriteLine("MethodDesc demo");

Console.ReadLine();

MDChlidClass cc = new MDChlidClass();

cc.VirtualFun1();

cc.VirtualFun2();

cc.IFun1();

cc.IFun2();

cc.InstanceFun1();

cc.InstanceFun2();

MDChlidClass.StaticFun1();

Console.ReadLine();

}

}

public class MDBaseClass

{

[MethodImpl(MethodImplOptions.NoInlining)]

public virtual void VirtualFun1()

{

Console.WriteLine("MDBaseClass VirtualFun1");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public virtual void VirtualFun2()

{

Console.WriteLine("MDBaseClass VirtualFun2");

}

}

public class MDChlidClass : MDBaseClass, IFoo

{

public static int TempInt = 0;

[MethodImpl(MethodImplOptions.NoInlining)]

public override void VirtualFun1()

{

Console.WriteLine("MDChlidClass VirtualFun1");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public override void VirtualFun2()

{

Console.WriteLine("MDChlidClass VirtualFun2");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public void IFun1()

{

Console.WriteLine("MDChlidClass IFun1");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public void IFun2()

{

Console.WriteLine("MDChlidClass IFun2");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public void InstanceFun1()

{

Console.WriteLine("MDChlidClass InstanceFun1");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public void InstanceFun2()

{

Console.WriteLine("MDChlidClass InstanceFun2");

}

[MethodImpl(MethodImplOptions.NoInlining)]

public static void StaticFun1()

{

Console.WriteLine("MDChlidClass StaticFun1");

}

}

public interface IFoo

{

void IFun1();

void IFun2();

}


  • 編譯代碼:


1

2

%windir%\Microsoft.NET\Framework\v2.0.50727\csc.exe /debug /target:exe /out:e:\temp\MethodDesc_2.0.exe e:\temp\MethodDesc.cs

pause


  • 運行 MethodDesc_2.0.exe

  • 啟動windbg 加載SOS

  • 查找對應的模塊:
    !Name2EE *!MethodDesc_2.0.exe

  • 根據模塊查找方法表:
    !DumpModule -mt 00af2c5c

  • 通過MDChlidClass方法表地址查看其EEClass 查找方法描述桶在EEClass偏移40h的位置(64位的話偏移60h 因為標記位使用不變 所有地址類型由4字節變成8字節):

!DumpMT -md 00af31e4

通過方法桶的地址00af3180觀察其下方法描述符:

  • 可以看到方法描述桶的第一個4字節(64位8字節)是方法表(MethodTable)的地址
    可以看到MDChlidClass的方法描述符(MD)

  • VirtualFun1?方法描述符地址:00af3190?其內容:00000008 20000004?第一個00代表方法入口在方法表(MT)后面以及還沒jit編譯,第二個00代表距方法描述桶(MethodDescChunk)的索引(便于找到桶的起始位置),后面的0008是方法的token末位 在編譯成IL時確定,可以通過ildasm查看 MethodDesc_2.0.exe 文件,這個token是在編譯期程序集內自增的,也就是在運行時并不是唯一的接下來的2000代表方法非內聯,0004代表方法表槽slot number 也就是方法入口(entrypoint)在方法表(MT)后的索引(索引從0開始 一般來說前4個方法都是從Object繼承下來的4個虛方法 除了接口類型),方法入口:00afc075

  • VirtualFun2?方法描述符地址:00af3198?其內容:00020009 20000005?依舊是沒jit編譯,方法入口在方法表后,token:0009,非內聯,slot number:0005,方法入口:00afc079

  • IFun1?方法描述符地址:00af31a0?其內容:0004000a 20000006?依舊是沒jit編譯,方法入口在方法表后,token:000a,非內聯,slot number:0006,方法入口:00afc07d

  • IFun2?方法描述符地址:00af31a8?其內容:0006000b 20000007?依舊是沒jit編譯,方法入口在方法表后,token:000b,非內聯,slot number:0007,方法入口:00afc081

  • InstanceFun1?方法描述符地址:00af31b0?其內容:4008000c 2000000a 00afc085?‘40’這位(bit)代表方法入口(slot)是跟在方法描述符(MD)后面的并非在方法表(MT)后面,依舊是沒jit編譯,方法入口在方法表后,token:000c,非內聯,slot number:000a(這里的slot number依然有值,但值是大于等方法表的slot長度的),方法入口:00afc085

  • InstanceFun2?方法描述符地址:00af31bc?其內容:400b000d 2000000b 00afc089?依舊是沒jit編譯,方法入口在方法描述符(MD)后,token:000d,非內聯,slot number:000b,方法入口:00afc089

  • StaticFun1?方法描述符地址:00af31c8?其內容:400b000e 2020000c 00afc08d?依舊是沒jit編譯,方法入口在方法描述符(MD)后,token:000e,2020非內聯 并且靜態,slot number:000c,方法入口:00afc08d

  • .ctor?實例構造方法 方法描述符地址:00af31d4?其內容:0011000f 00000008?依舊是沒jit編譯,方法入口在方法表后,token:000f,slot number:0008,方法入口:00afc091

  • .cctor?靜態構造方法 方法描述符地址:00af31dc?其內容:00130010 00200009?依舊是沒jit編譯,方法入口在方法表后,token:0010,靜態的:0020,slot number:0009,方法入口:00afc095

可以看到所有的虛方法(繼承或者實現接口)以及構造器方法(實例或者靜態)的方法入口(slot)都是在方法表后面的,而其他實例方法和靜態方法的方法入口(slot)是跟在方法描述符(MD)后面的

這里引用下CLR文檔的一段:
Each MethodDesc has a slot, which contains the entry point of the method. The slot and entry point must exist for all methods, even the ones that never run like abstract methods. There are multiple places in the runtime that depend on the 1:1 mapping between entry points and MethodDescs, making this relationship an invariant.
The slot is either in MethodTable or in MethodDesc itself. The location of the slot is determined by mdcHasNonVtableSlot bit on MethodDesc.
The slot is stored in MethodTable for methods that require efficient lookup via slot index, e.g. virtual methods or methods on generic types. The MethodDesc contains the slot index to allow fast lookup of the entry point in this case.

接下來讓 MethodDesc_2.0.exe 繼續執行,并回車跳過第一個ReadLine(),再中斷到調試器,觀察MDChlidClass的方法表00af31e4(MT)和其方法描述桶00af3180(MDC)

可以看到所有Jit編譯過的方法,其方法描述符的 00h或者40h 會 邏輯??31h,都是按位的,其中30h是安全描述符先忽略,01h代表是否Jit編譯過,同時所有Jit編譯過的方法其方法入口(entrypoint)會更新

更新安全描述符:






先更新方法入口,再更新是否Jit編譯標記位:
https://github.com/dotnet/coreclr/blob/master/src/vm/method.cpp#L5099






0:000> uf mscorwks!MethodDesc::SetStableEntryPointInterlocked

mscorwks!MethodDesc::SetStableEntryPointInterlocked:

79ed9a27 55 ? ? ? ? ? ? ?push ? ?ebp

79ed9a28 8bec ? ? ? ? ? ?mov ? ? ebp,esp

79ed9a2a 53 ? ? ? ? ? ? ?push ? ?ebx

79ed9a2b 56 ? ? ? ? ? ? ?push ? ?esi

79ed9a2c 57 ? ? ? ? ? ? ?push ? ?edi

79ed9a2d 8bf9 ? ? ? ? ? ?mov ? ? edi,ecx

79ed9a2f e8b96afbff ? ? ?call ? ?mscorwks!MethodDesc::GetTemporaryEntryPoint (79e904ed)

79ed9a34 8bcf ? ? ? ? ? ?mov ? ? ecx,edi

79ed9a36 8bd8 ? ? ? ? ? ?mov ? ? ebx,eax

79ed9a38 e8156bfbff ? ? ?call ? ?mscorwks!MethodDesc::GetAddrOfSlot (79e90552)

79ed9a3d 8b5508 ? ? ? ? ?mov ? ? edx,dword ptr [ebp+8]

79ed9a40 53 ? ? ? ? ? ? ?push ? ?ebx

79ed9a41 8bc8 ? ? ? ? ? ?mov ? ? ecx,eax

79ed9a43 ff15d0c33c7a ? ?call ? ?dword ptr [mscorwks!FastInterlockCompareExchange (7a3cc3d0)]

79ed9a49 8bf0 ? ? ? ? ? ?mov ? ? esi,eax

79ed9a4b 2bf3 ? ? ? ? ? ?sub ? ? esi,ebx

79ed9a4d f7de ? ? ? ? ? ?neg ? ? esi

79ed9a4f 1bf6 ? ? ? ? ? ?sbb ? ? esi,esi

79ed9a51 46 ? ? ? ? ? ? ?inc ? ? esi

79ed9a52 ba00000001 ? ? ?mov ? ? edx,1000000h

79ed9a57 8bcf ? ? ? ? ? ?mov ? ? ecx,edi

79ed9a59 ff1574c23c7a ? ?call ? ?dword ptr [mscorwks!FastInterlockOr (7a3cc274)]

79ed9a5f 5f ? ? ? ? ? ? ?pop ? ? edi

79ed9a60 8bc6 ? ? ? ? ? ?mov ? ? eax,esi

79ed9a62 5e ? ? ? ? ? ? ?pop ? ? esi

79ed9a63 5b ? ? ? ? ? ? ?pop ? ? ebx

79ed9a64 5d ? ? ? ? ? ? ?pop ? ? ebp

79ed9a65 c20400 ? ? ? ? ?ret ? ? 4


  • 可以通過?DumpMD?SOS擴展命令觀察方法描述符:

為毛要研究方法描述符這個東西?
方法描述符在CLR運行時作為方法的最基礎服務,繼承多態在運行時的實現依賴方法描述符,接口多態的運行時DispatchToken以及實現也依賴.

參考文檔:

https://github.com/dotnet/coreclr/blob/master/Documentation/botr/method-descriptor.md
https://github.com/dotnet/coreclr/blob/master/src/vm/methodtablebuilder.cpp
https://github.com/dotnet/coreclr/blob/master/src/vm/method.hpp
http://blogs.microsoft.co.il/sasha/2009/09/27/how-are-methods-compiled-just-in-time-and-only-then/

原文地址:https://espider.github.io/CLR/method-descriptor/


.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

贊賞

人贊賞

總結

以上是生活随笔為你收集整理的CLR运行时细节 - Method Descriptor的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产一区精品在线观看 | av手机免费在线观看 | 狠狠躁日日躁 | 亚洲免费视 | 鲁鲁久久 | 伊人爱爱网 | 精品人妻无码一区二区色欲产成人 | 欧美激情自拍 | 成人国产精品免费 | 天天摸天天爽 | 四季av日韩精品一区 | 亚洲欧美在线综合 | 欧美精品免费一区二区 | 亚洲网站在线免费观看 | 美国一区二区三区 | 一区二区三区 欧美 | 国产精品成人久久电影 | 欧美一级电影在线 | 国产精品99久久久久久一二区 | www.亚洲 | 色亚洲成人 | 精品香蕉视频 | 黑人一区二区三区 | 五月天婷婷久久 | 亚洲黄色大片 | 国产一区二区三区精品愉拍 | 2019天天干天天操 | 欧美激情成人 | 激情五月在线观看 | 色一五月 | 亚洲人成无码网站久久99热国产 | www.麻豆av.com | 九九热视频免费观看 | 狠狠人妻久久久久久综合蜜桃 | 未满十八岁勿进 | 国产性―交一乱―色―情人 | 欧美日韩在线观看视频 | 国产精品福利一区二区三区 | 午夜视频在线看 | 国产三极片 | 国产精品二区在线观看 | 中文字幕无码精品亚洲资源网久久 | 亚洲AV成人无码网站天堂久久 | 天堂在线资源网 | 成人免费无码大片a毛片抽搐色欲 | 成人黄色短片 | 1024毛片| 久久123| 琪琪在线视频 | 色爱av综合网 | 久射久| 欧美一级专区 | 久久亚洲精 | 精品国产a线一区二区三区东京热 | 综合五月| 三级黄色网络 | 校园sm主奴调教1v1罚视频 | 北条麻妃青青久久 | 中文字幕一区二区不卡 | 性欧美巨大 | 91在线观看免费高清 | 精品在线视频一区 | 影音先锋国产精品 | 99久久精品无免国产免费 | 欧美在线不卡 | 性做久久久久久久久久 | 亚洲字幕在线观看 | 99资源| 青青草原亚洲视频 | 色网导航站 | 亚洲综合不卡 | 国产超碰人人 | 在线日韩成人 | 亚洲综合p | 少妇高清精品毛片在线视频 | 成年人视频在线播放 | 天天插天天操天天干 | 一区二区免费在线 | 天天干夜夜操视频 | 欧洲一区二区在线观看 | 网友自拍视频 | 毛片a | 日本一级淫片 | 欧美日在线 | 日韩欧美在线精品 | 少妇太爽了太深了太硬了 | 一级艳片新婚之夜 | 国产精品综合一区二区 | 亚洲无限看 | 91亚洲精品一区 | 大香蕉毛片 | 国产精品影音先锋 | 国产人妖在线 | 欧美黄色大片免费看 | 春宵av| 亚洲 成人 av | 国产女人18毛片水真多18精品 | 在线观看亚洲国产 | 欧美一区中文字幕 |