CoreCLR源码探索(七) JIT的h5牛牛源码出售工作原理(入门篇)

很多C#的初学h5牛牛源码出售Q1446595067官网:h5.haozibbs.com者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的?

最简单的解答是, C#会通过编译器(CodeDom, Roslyn)编译成IL代码,

然后CLR(.Net Framework, .Net Core, Mono)会把这些IL代码编译成目标机器的机器代码并执行.

相信大多数的C#的书籍都是这样一笔带过的.

这篇和下篇文章会深入讲解JIT的具体工作流程,

和前面的GC篇一样, 实现中的很多细节都是无标准文档的, 用搜索引擎不会找到它们相关的资料.

因为内容相当多, 讲解JIT的文章将会分为两篇.

第一篇是入门篇, 看过这个系列之前的文章和CLR via C#, 了解一些编译原理的都可以看的明白.

第二篇是详解篇, 会分析JIT的具体实现流程, 算法和数据结构.

这篇的内容是基于CoreCLR 1.1.0分析的, 其他CLR中的实现不一定和这篇分析的实现完全一样.

微软最近提供了一篇JIT入门文档,

尽管里面写的相当潦草但是仍有很大的参考价值, 推荐同时参考这个文档.

JIT的作用介绍

相信很多C#程序员都知道, 我们编写的C#代码在经过编译后得出的exe或dll里面包含的并不是机器代码,

而是一种中间代码, 也称为MSIL(简称IL).

MSIL可以在不同的系统或者平台上执行, CLR中执行它们的模块就是这篇要讲的JIT.

如图所示

CoreCLR中的JIT代号是RyuJIT, RyuJIT可以把MSIL翻译为X86, X64或者ARM的机器代码.

使用JIT的好处有

使用JIT的坏处有

为了解决这些坏处而出现的技术有NGEN, AOT, CoreRT等, 但是使用它们以后同时也就失去了使用JIT的好处.

JIT的流程总览

以下的图片来源于微软提供的JIT入门文档:

总体上来说RyuJIT可以分为两个部分.

前端: 也就是图上的第一行, 负责把MSIL转换为JIT中的内部表现(IR)并且执行优化.

后端: 也就是图上的第二行, 负责准备生产机器代码, 分配寄存器等与平台相关的处理.

具体的步骤可以分为:

前端的步骤有(导入MSIL和优化):

后端的步骤有(平台相关的处理):

JIT的流程实例

只看上面的图你可能会一头雾水, 我们来看看实际的流程.

为了更容易理解这里我使用的是Debug模式.

以下的内容来源于CoreCLR的输出, 设置环境变量"COMPlus_JitDump=Main"并且使用Debug版的CoreCLR即可得到.

首先是C#代码, 非常简单的循环3次并且输出到控制台.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
for (int x = 0; x < 3; ++x)
{
Console.WriteLine(x);
}
}
}
}

经过编译后会生成以下的IL, 下面我标记了运行堆栈的状态和简单的注释.

IL to import:
IL_0000 00
nop
IL_0001 16
ldc.i4.0
; 运行堆栈 [ 0 ]
IL_0002 0a
stloc.0
; 运行堆栈 [ ], 保存到本地变量0 (x = 0)
IL_0003 2b 0d
br.s
13 (IL_0012) ; 跳转到IL_0012
IL_0005 00
nop
IL_0006 06
ldloc.0
; 运行堆栈 [ x ]
IL_0007 28 0c 00 00 0a call
0xA00000C ; 运行堆栈 [ ], 调用Console.WriteLine, 这里的0xA00000C是token
IL_000c 00
nop
IL_000d 00
nop
IL_000e 06
ldloc.0
; 运行堆栈 [ x ]
IL_000f 17
ldc.i4.1
; 运行堆栈 [ x, 1 ]
IL_0010 58
add
; 运行堆栈 [ x+1 ]
IL_0011 0a
stloc.0
; 运行堆栈 [ ], 保存到本地变量0 (x = x + 1)
IL_0012 06
ldloc.0
; 运行堆栈 [ x ]
IL_0013 19
ldc.i4.3
; 运行堆栈 [ x, 3 ]
IL_0014 fe 04
clt
; 运行堆栈 [ x<3 ]
IL_0016 0b
stloc.1
; 运行堆栈 [ ], 保存到本地变量1 (tmp = x < 3)
IL_0017 07
ldloc.1
; 运行堆栈 [ tmp ]
IL_0018 2d eb
brtrue.s
-21 (IL_0005); 运行堆栈 [ ], 如果tmp为true则跳转到IL_0005
IL_001a 2a
ret
; 从函数返回

RyuJIT的前端会把IL导入为中间表现(IR), 如下

Importing BB02 (PC=000) of ‘ConsoleApplication.Program:Main(ref)‘
[ 0] 0 (0x000) nop
[000004] ------------
* stmtExpr void (IL 0x000... ???)
[000003] ------------
\--* no_op
void
[ 0] 1 (0x001) ldc.i4.0 0
[ 1] 2 (0x002) stloc.0
[000008] ------------
* stmtExpr void (IL 0x001... ???)
[000005] ------------
| /--* const
int 0
[000007] -A----------
\--* =
int
[000006] D------N----
\--* lclVar int V01 loc0
[ 0] 3 (0x003) br.s
[000010] ------------
* stmtExpr void (IL 0x003... ???)
[000009] ------------
\--* nop
void

Importing BB03 (PC=005) of ‘ConsoleApplication.Program:Main(ref)‘
[ 0] 5 (0x005) nop
[000025] ------------
* stmtExpr void (IL 0x005... ???)
[000024] ------------
\--* no_op
void
[ 0] 6 (0x006) ldloc.0
[ 1] 7 (0x007) call 0A00000C
[000029] ------------
* stmtExpr void (IL 0x006... ???)
[000027] --C-G-------
\--* call
void System.Console.WriteLine
[000026] ------------ arg0
\--* lclVar int V01 loc0
[ 0] 12 (0x00c) nop
[000031] ------------
* stmtExpr void (IL 0x00C... ???)
[000030] ------------
\--* no_op
void
[ 0] 13 (0x00d) nop
[000033] ------------
* stmtExpr void (IL 0x00D... ???)
[000032] ------------
\--* no_op
void
[ 0] 14 (0x00e) ldloc.0
[ 1] 15 (0x00f) ldc.i4.1 1
[ 2] 16 (0x010) add
[ 1] 17 (0x011) stloc.0
[000039] ------------
* stmtExpr void (IL 0x00E... ???)
[000035] ------------
|
/--* const
int 1
[000036] ------------
| /--* +
int
[000034] ------------
| | \--* lclVar int V01 loc0
[000038] -A----------
\--* =
int
[000037] D------N----
\--* lclVar int V01 loc0
Importing BB04 (PC=018) of ‘ConsoleApplication.Program:Main(ref)‘
[ 0] 18 (0x012) ldloc.0
[ 1] 19 (0x013) ldc.i4.3 3
[ 2] 20 (0x014) clt
[ 1] 22 (0x016) stloc.1
[000017] ------------
* stmtExpr void (IL 0x012... ???)
[000013] ------------
|
/--* const
int 3
[000014] ------------
| /--* <
int
[000012] ------------
| | \--* lclVar int V01 loc0
[000016] -A----------
\--* =
int
[000015] D------N----
\--* lclVar int V02 loc1
[ 0] 23 (0x017) ldloc.1
[ 1] 24 (0x018) brtrue.s
[000022] ------------
* stmtExpr void (IL 0x017... ???)
[000021] ------------
\--* jmpTrue void
[000019] ------------
| /--* const
int 0
[000020] ------------
\--* !=
int
[000018] ------------
\--* lclVar int V02 loc1
Importing BB05 (PC=026) of ‘ConsoleApplication.Program:Main(ref)‘
[ 0] 26 (0x01a) ret
[000042] ------------
* stmtExpr void (IL 0x01A... ???)
[000041] ------------
\--* return void

我们可以看到IL被分成了好几组(BB02~BB05), 这里的BB是BasicBlock的缩写,

一个BasicBlock中有多个语句(Statement), 一个语句就是一棵树(GenTree).

上面的文本对应了以下的结构(又称HIR结构):

原文地址:https://www.cnblogs.com/uuuu01/p/8513561.html

时间: 2024-10-10 22:42:06

CoreCLR源码探索(七) JIT的h5牛牛源码出售工作原理(入门篇)的相关文章

微信h5牛牛源码出售 手机牛牛搭建图文教程

微信h5牛牛源码出售QQ:2152876294官网http://diguaym.com/h5手机17070838768神兽青龙白虎朱雀玄武凤凰大厅搭建如下: 1. 布局的时候,如果一个元素你想让他的宽高保持一定比例,而不随屏幕变化,宽高设置的时候,使用同一个单位都是CSS3的单位,低版本不兼容 <span style="font-family: Arial, sans-serif; ">1.移动端页面布局,使用相对的数值,不要使用绝对数值,推荐使用%,vw,vh,rem,e

h5牛牛源码开发程序员是出轨率最高的群体?欲加之罪何患无辞

现代人为人处事,会自黑算是必备技能之一h5牛牛源码开发(h5.hxforum.com) 联系方式170618633533企鹅2952777280源码出售 房卡出售 后台出租有意者私聊扣扣.其原因主要有二:一是为了化解尴尬,二是缓解压力,这样集幽默与智慧于一身,大家何乐而不为?但是如今,是什么力量,让一个「从来都是自嘲不息,哪轮得到人家来黑」的程序员群体在光天化日之下就"被黑"了? 为什么程序员就成了出轨率最高的群体了?近日一篇<为什么程序员是出轨率最高的群体>的文章引发诸多

微信h5牛牛源码搭建 问题修复

需要参数 mch_id-商户号,nonce_str-随机字符串,sign-签名,前面两个参数好说,后面的 sign看得我是一脸懵逼,经过 几 次测试最后得到sign的代码是这样的: SortedMap<String, String> datas = new TreeMap<String, String>(); String uuid = UUID.randomUUID().toString().replaceAll("-", ""); dat

Egret 学习笔记 h5牛牛源码 h5牛牛源码搭建教程

1.纹理集实际上就是将一些零碎的小图放到一张大图当中.游戏中也经常使用到纹理集.使用纹理集的好处很多,我们通过将大量的图片拼合为一张图片从而减少网络请求,原先加载数次的图片资源现在加载一次即可.同时,在引擎渲染的时候也会减少IO读取,从而提高h5牛牛源码性能.h5牛牛源码Q 2171793408     http://wowotouba.com/h52.只要发生事件,Flash就会调度事件对象.如果事件目标不在显示列表中,则Flash Player或AIR将事件对象直接调度到事件目标.例如,Fl

分析h5牛牛制作服务器的架构(总体设计篇)

h5牛牛制作服务器的架构交流论坛:aqiulian.com,更多服务器的架构咨询Q:212303635.首先要说明的是, 这个棋牌游戏的服务器架构参考了网狐棋牌的架构.网狐棋牌最令人印象深刻的是其稳定性和高网络负载.它的一份压力测试报告上指出:一台双核r的INTEL Xeon 2.8CPU加上2G内存和使用共享100M光纤的机子能够支持5000人同时在线游戏. 在研究其服务器框架后发现,它的网络部分确实是比较优化的.它主要采用了Windows提供的IO完成端口来实现其网络组件.本服务器虽然参考了

H5牛牛源码开发APP技术总结

Q1446595067官网:h5.haozibbs.com或http:\\www.aqbaa.cn在H5页面打开APP的方法一般有两种,在IOS 9以前,一般使用的技术是URL Scheme.这种方式虽然可自定义程度很高,能够巧妙地实现很多跳转,但弊端也很明显:我们只能通过 scheme://example 这种格式的链接来实现跳转,而且现在苹果还对这种方式的跳转加了一个提示框:"是否打开XXX".对于对Web和原生App交互的场景需求量很大的产品来说,这样的跳转方式显然是步骤冗杂的,

新版H5牛牛源码搭建一条龙教程

最低配置:linux服务器,系统: CentOS 6.8,内存2G以上,独享5M以上带宽 QQ:2164097691  材料下载:h5.hubawl.com 源码 <!--{template common/header}--> <!--[name]{lang portalcategory_listtplname}[/name]--> <!--{eval $list = array();}--> <!--{eval $wheresql = category_get_

h5牛牛源码出售中 audio标签的样式修改

Q1446595067官网:h5.haozibbs.com由于html5的流行,现在移动端大多数的需求都可以使用audio来播放音频,但您可能只是需要很简单的播放/停止效果,但不同的浏览器上的audio样式却不尽人意,那么要怎么改变这个样式呢,其实它的原理比较简单,就是把写audio的时候不要用controls属性,隐藏原生的audio, 然后用div之类标签,定义css样式美化起来用来显示播放器的效果,最后用js捕获audio事件,基本就是src路径.pause暂停.load加载.play播放

h5牛牛源码搭建建站成功第一步——域名的选择

有问题Q1446595067官网:h5.haozibbs.com 一个游戏网站开始于名称和域名,大型公司对这个尤其重视,因为好的名称和相应的域名能够很好的被人记住,才能有好的访问量和多的游戏玩家. 有人说,域名是地皮,网站是楼盘,位置决定成败.在房产市场,好的地皮价格贵,随着进驻的商家越来越多,价格也就水涨船高,域名的售价不断在刷新新的记录,众多的游戏厂商们,不停的往门槛里挤,谁也不愿意输在起跑线上. 域名是棋牌游戏网站建设的第一步,选择域名需要从域名的长度.后缀.含义.优化等各个方面考虑其价值