自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

.Net8的AOT是如何被C++操控運(yùn)行的

開發(fā) 前端
C++和AOT無論是Roslyn,或者ILC或者引導(dǎo)程序BootStrap都是通過C++來啟動(dòng)運(yùn)行的。1.Roslyn的運(yùn)行實(shí)質(zhì)上是運(yùn)行在虛擬機(jī)CLR上面的2.ILC同上3.BootStrap它本身就是cpp項(xiàng)目而llvm本身就是一套超級底層的C/C++項(xiàng)目,可以看到在一整套的AOT編譯運(yùn)行流程中,C++始終操控C#的運(yùn)行。

前言

.Net目前有兩條線,一條是正宗的.Net虛擬機(jī)CLR調(diào)用JIT的即時(shí)編譯,另外一條就是通過ILC編譯成本地的機(jī)器碼也即是AOT。上一篇【C++是如何運(yùn)行C#/.Net的?】說的是前者,本篇來看下后者。

概括

前情提要:本篇以最新的.Net8 PreView5為藍(lán)本,進(jìn)行的描述。

1.不同簡要比較

AOT相當(dāng)于一個(gè)全新的縮減.Net版本,它和即時(shí)編譯器也即JIT機(jī)器碼照樣不同,這里舉一個(gè)例子,比如以下代碼:

static void Main(string[] args)
{
    Program pm = new Program();
}

簡單的一個(gè)對象實(shí)例化,即時(shí)編譯里面:

call        JIT_TrialAllocSFastMP_InlineGetThread (07FFC4C650650h)  
 mov         qword ptr [rbp+20h],rax  
 mov         rcx,qword ptr [rbp+20h]  
 call        Program..ctor() (07FFBECC2C078h)

可以看到它先分配內(nèi)存,然后調(diào)用默認(rèn)的構(gòu)造函數(shù).ctor

那么AOT呢?

00007FF72AD459E8 48 8D 0D E1 55 17 00 lea         rcx,[repro_Program::`vftable' (07FF72AEBAFD0h)]  
00007FF72AD459EF E8 9C 0A C9 FF       call        RhpNewFast (07FF72A9D6490h)

它這里很明顯用了虛函數(shù)表指針作為參數(shù),調(diào)用了RhpNewFast。完全是不一樣的。

2.整體過程AOT的編譯如下:C#源碼-》Roslyn(DLL)->ILC(Obj)->Link(Exe)寫好了C#源代碼之后,Roslyn會(huì)接管C#源代碼把它編譯成中間語言MSIL,存放在托管的動(dòng)態(tài)鏈接庫即DLL里面。ILC會(huì)接管托管的DLL把它生成目標(biāo)文件.Obj,然后用NativeAot的引導(dǎo)程序也即Bootstrap引導(dǎo)Link.exe工具鏈接.Obj目標(biāo)文件生成可執(zhí)行文件。

3.細(xì)節(jié)生成的目標(biāo)文件也即Obj依舊是通過開源界三大編譯器之一的LLVM來生成的.在Windows/Linux/MaoOS上的動(dòng)態(tài)鏈接庫分別是:

objwriter.dll(pe)/libobjwriter.so(elf)/libobjwriter.dylib(Mach-O)

他們分別封裝了各個(gè)平臺的llvm后端代碼生成來完成了Obj目標(biāo)文件的生成。

4.C++和AOT無論是Roslyn,或者ILC或者引導(dǎo)程序BootStrap都是通過C++來啟動(dòng)運(yùn)行的。1.Roslyn的運(yùn)行實(shí)質(zhì)上是運(yùn)行在虛擬機(jī)CLR上面的2.ILC同上3.BootStrap它本身就是cpp項(xiàng)目而llvm本身就是一套超級底層的C/C++項(xiàng)目,可以看到在一整套的AOT編譯運(yùn)行流程中,C++始終操控C#的運(yùn)行。

5.核心代碼

為了更為透徹的了解到ILC調(diào)用Objwriter.dll動(dòng)態(tài)鏈接庫操控llvm生成obj目標(biāo)文件。在WinX64平臺上,這里演示一段簡單的代碼,步驟如下:

一.首先在nuget上面下載一個(gè)ILC編譯器,也即是:

runtime.win-x64.Microsoft.DotNet.ILCompiler

二.找到nuget目錄,里面有個(gè)objwriter.dll一般的在如下路徑:

C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.8\tools

三.新建一個(gè)C#控制臺項(xiàng)目名字Obj,把上面的路徑找到的objwriter.dll放入到

Obj項(xiàng)目bin/Debug/net7.0目錄下面。

四.Obj項(xiàng)目bin/Debug/net7.0目錄下面新建一個(gè)Demo.obj目標(biāo)文件

五.Program.cs里面填寫如下代碼:

internal class Program
{
    [DllImport("objwriter.dll")]
    private static extern IntPtr InitObjWriter([MarshalAs(UnmanagedType.LPUTF8Str)] string objectFilePath, string triple = null);


    [DllImport("objwriter.dll")]
    private static extern void FinishObjWriter(IntPtr objWriter);


    [DllImport("objwriter.dll")]
    private static extern void EmitIntValue(IntPtr objWriter, ulong value, int size);


    private IntPtr _nativeObjectWriter = IntPtr.Zero;


    static void Main(string[] args)
    {
            IntPtr objectWriter = InitObjWriter("Demo.obj", "x86_64-pc-win32-windows");
            EmitIntValue(objectWriter, 0x10, 4);
            FinishObjWriter(objectWriter);
    }
}

運(yùn)行這段代碼之后,打開Demo.obj可以看到文件里面寫入了一段內(nèi)容,這就是ILC編譯器往obj目標(biāo)文件里面寫入被JIT編譯后的機(jī)器碼的核心部分代碼的原型。這里因?yàn)榉庋b了llvm的細(xì)節(jié),又因托管省略了大部分,看起來比較簡潔。綜合起來實(shí)際上的代碼高達(dá)百萬行之巨,暫不贅述此部分。

以上代碼GitHub下載地址:

https://github.com/tangyanzhi/jianghupt/releases/download/llvm/Obj.rar

責(zé)任編輯:武曉燕 來源: 江湖評談
相關(guān)推薦

2023-07-11 00:17:58

.Net8AOTC

2023-09-11 08:40:34

AOTVMP代碼

2023-11-17 13:42:06

.NET8C#工具

2023-07-14 08:29:55

AOT.Net程序

2023-11-28 12:01:06

C++STL

2023-11-17 08:52:32

.NET8C#

2025-04-02 07:40:30

2023-10-07 10:16:18

.Net8GC內(nèi)存

2024-10-11 14:42:59

2019-08-28 14:21:39

C++C接口代碼

2020-07-31 18:33:56

C++編程語言

2024-08-30 09:21:28

2023-12-15 17:09:28

.NET8Primitives性能

2025-04-01 04:03:00

.NET8C#CPU

2009-10-10 14:07:56

2024-11-07 12:33:47

2023-11-06 10:03:01

.Net8類型轉(zhuǎn)換

2010-01-26 15:51:06

C++變量

2014-09-19 10:46:36

LuaCC++

2014-04-17 10:37:43

C++.NET Native
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號