当前位置:首页>热门 > >正文

.Net8顶级技术:边界检查之IR解析(二)

  • 2023-05-24 08:28:45来源:博客园
前言

IR技术应用在各个编程语言当中,它属于JIT的核心部分,确实有点点麻烦。但部分基本明了。本篇通过.Net8里面的边界检查的小例子了解下。前情提要,看这一篇之前建议看看前一篇:点击此处,以便于理解。

概括

1.前奏先上C#代码:

[MethodImpl(MethodImplOptions.NoInlining)]private static bool Test(int[] array){   for (int i = 0; i < 0x12345; i++)   {      if (array[i] == 42)      {         return true;      }   }  return false;}

Test函数经过Roslyn编译成IL代码之后,会被JIT导入及操作变成IR。


(资料图片仅供参考)

BBnum BBid ref try hnd preds           weight    lp [IL range]     [jump]      [EH region]         [flags]-----------------------------------------------------------------------------------------------------------------------------------------BB01 [0007]  1                             1       [???..???)-> BB04 ( cond )                     internal BB02 [0001]  2       BB01,BB03             4     0 [004..00B)-> BB05 ( cond )                     i Loop idxlen bwd bwd-target align BB03 [0003]  1       BB02                  4     0 [00D..019)-> BB02 ( cond )                     i bwd BB04 [0005]  2       BB01,BB03             0.50    [019..01B)        (return)                     i BB05 [0002]  1       BB02                  0.50    [00B..00D)        (return)                     i -----------------------------------------------------------------------------------------------------------------------------------------

可以看到IL被分割成了五个BB(basic block).注意表格的BBnum和jump列。BB01的BBnum就是BB01,它的jump是BB04。为啥是BB04?因为BB01的IR表示的是如果(i>=0x12345),则跳转到BB04,也就是BB01的正常逻辑。下面看下这个五个BB.

------------ BB01 [???..???) -> BB04 (cond), preds={} succs={BB02,BB04}***** BB01STMT00006 ( 0x011[E-] ... ??? )     (  7,  9) [000038] -----------                         *  JTRUE     void       (  5,  7) [000039] J------N---                         \--*  GE        int        (  3,  2) [000040] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  4) [000041] -----------                            \--*  CNS_INT   int    0x12345------------ BB02 [004..00B) -> BB05 (cond), preds={BB01,BB03} succs={BB03,BB05}***** BB02STMT00002 ( 0x004[E-] ... 0x009 )               [000013] ---XG+-----                         *  JTRUE     void                 [000012] N--XG+-N-U-                         \--*  EQ        int                  [000034] ---XG+-----                            +--*  COMMA     int                  [000026] ---X-+-----                            |  +--*  BOUNDS_CHECK_Rng void                 [000008] -----+-----                            |  |  +--*  LCL_VAR   int    V01 loc0                        [000025] ---X-+-----                            |  |  \--*  ARR_LENGTH int                  [000007] -----+-----                            |  |     \--*  LCL_VAR   ref    V00 arg0                        [000035] n---G+-----                            |  \--*  IND       int                  [000033] -----+-----                            |     \--*  ARR_ADDR  byref int[]               [000032] -----+-----                            |        \--*  ADD       byref                [000023] -----+-----                            |           +--*  LCL_VAR   ref    V00 arg0                        [000031] -----+-----                            |           \--*  ADD       long                 [000029] -----+-----                            |              +--*  LSH       long                 [000027] -----+---U-                            |              |  +--*  CAST      long <- uint               [000024] -----+-----                            |              |  |  \--*  LCL_VAR   int    V01 loc0                        [000028] -----+-N---                            |              |  \--*  CNS_INT   long   2               [000030] -----+-----                            |              \--*  CNS_INT   long   16               [000011] -----+-----                            \--*  CNS_INT   int    42------------ BB03 [00D..019) -> BB02 (cond), preds={BB02} succs={BB04,BB02}***** BB03STMT00003 ( 0x00D[E-] ... 0x010 )               [000018] -A---+-----                         *  ASG       int                  [000017] D----+-N---                         +--*  LCL_VAR   int    V01 loc0                        [000016] -----+-----                         \--*  ADD       int                  [000014] -----+-----                            +--*  LCL_VAR   int    V01 loc0                        [000015] -----+-----                            \--*  CNS_INT   int    1***** BB03STMT00001 ( 0x011[E-] ... 0x017 )     (  7,  9) [000006] -----------                         *  JTRUE     void       (  5,  7) [000005] J------N---                         \--*  LT        int        (  3,  2) [000003] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  4) [000004] -----------                            \--*  CNS_INT   int    0x12345------------ BB04 [019..01B) (return), preds={BB01,BB03} succs={}***** BB04STMT00005 ( 0x019[E-] ... 0x01A )               [000022] -----+-----                         *  RETURN    int                  [000037] -----+-----                         \--*  CNS_INT   int    0------------ BB05 [00B..00D) (return), preds={BB02} succs={}***** BB05STMT00004 ( 0x00B[E-] ... 0x00C )               [000020] -----+-----                         *  RETURN    int                  [000036] -----+-----                         \--*  CNS_INT   int    1

preds表示能在逻辑上执行到当前块的所有快,succs表示当前语句逻辑能达到的BB块。举个例子:比如BB01,首先看下这条IR表示的如果(i>=0x12345),则跳转到BB04,也就是直接返回0。因为逻辑是索引大于了循环的最大次数,是不合理的。如果(i<0x12345),则跳转到BB02,也就是判断(array[i]是否等于42)。上面BB01的predes为空,则表示没有逻辑能达到这条语句。它的succs为BB02和BB04,跟上面的推测吻合。其它依次类推。

2.BB的IR表示通过上面的BB01到BB05的观察,得知它们分别表示如下:一:BB01

if(i>=0x12345)

二:BB02

if(array[i]==42)

三:BB03

i=i+1;if(i<0x12345)

四:BB04

return 0

五:BB05

return 1

以上循环被分割成了五个BB。它的实际逻辑如下:

if(i>=0x12345){  return flase;}else{  for(i<0x12345;i++)  {    if(array[i]==42)    {      return true;    }  }  return flase;}

所以呢,实际是示例的for循环,被分解成了上面的代码。但是还没完,为了确保这个array[i]不会出现内存访问的错误,BB02里面有个BOUNDS_CHECK_Rng的边界检查技术,它会判断array[i]里的i索引是否查过array.length的长度,因为在for循环里面,所以每次都会判断,会增加相应的开销。为了达到最优的效果,.Net8会去掉这开销。那么应该怎么做呢?继续看。JIT先增加BB06,BB07,BB08,BB09四个块,然后把BOUNDS_CHECK_Rng给去掉。去掉前后对比如下。去掉前:

[000013] ---XG+-----                         *  JTRUE     void                 [000012] N--XG+-N-U-                         \--*  EQ        int                  [000034] ---XG+-----                            +--*  COMMA     int                  [000026] ---X-+-----                            |  +--*  BOUNDS_CHECK_Rng void                 [000008] -----+-----                            |  |  +--*  LCL_VAR   int    V01 loc0                        [000025] ---X-+-----                            |  |  \--*  ARR_LENGTH int                  [000007] -----+-----                            |  |     \--*  LCL_VAR   ref    V00 arg0                        [000035] n---G+-----                            |  \--*  IND       int                  [000033] -----+-----                            |     \--*  ARR_ADDR  byref int[]               [000032] -----+-----                            |        \--*  ADD       byref                [000023] -----+-----                            |           +--*  LCL_VAR   ref    V00 arg0                        [000031] -----+-----                            |           \--*  ADD       long                 [000029] -----+-----                            |              +--*  LSH       long                 [000027] -----+---U-                            |              |  +--*  CAST      long <- uint               [000024] -----+-----                            |              |  |  \--*  LCL_VAR   int    V01 loc0                        [000028] -----+-N---                            |              |  \--*  CNS_INT   long   2               [000030] -----+-----                            |              \--*  CNS_INT   long   16               [000011] -----+-----                            \--*  CNS_INT   int    42

去掉后:

[000013] ----G+-----                         *  JTRUE     void                 [000012] N---G+-N-U-                         \--*  EQ        int                  [000034] ----G+-N---                            +--*  COMMA     int                  [000026] -----+-----                            |  +--*  NOP       void                 [000035] n---G+-----                            |  \--*  IND       int                  [000033] -----+-----                            |     \--*  ARR_ADDR  byref int[]               [000032] -----+-----                            |        \--*  ADD       byref                [000023] -----+-----                            |           +--*  LCL_VAR   ref    V00 arg0                        [000031] -----+-----                            |           \--*  ADD       long                 [000029] -----+-----                            |              +--*  LSH       long                 [000027] -----+---U-                            |              |  +--*  CAST      long <- uint               [000024] -----+-----                            |              |  |  \--*  LCL_VAR   int    V01 loc0                        [000028] -----+-N---                            |              |  \--*  CNS_INT   long   2               [000030] -----+-----                            |              \--*  CNS_INT   long   16               [000011] -----+-----                            \--*  CNS_INT   int    42

然后再新增BB10,BB11,BB12,BB13四个BB块。这些BB块如下所示:

------------ BB01 [???..???) -> BB12 (cond), preds={} succs={BB02,BB12}***** BB01STMT00006 ( 0x011[E-] ... ??? )     (  7,  9) [000038] -----------                         *  JTRUE     void       (  5,  7) [000039] J------N---                         \--*  GE        int        (  3,  2) [000040] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  4) [000041] -----------                            \--*  CNS_INT   int    0x12345------------ BB02 [???..???), preds={BB01} succs={BB03}------------ BB03 [???..???) -> BB09 (cond), preds={BB02} succs={BB04,BB09}***** BB03STMT00010 ( ??? ... ??? )     (  7,  6) [000072] -----------                         *  JTRUE     void       (  5,  4) [000071] J------N---                         \--*  EQ        int        (  3,  2) [000069] -----------                            +--*  LCL_VAR   ref    V00 arg0              (  1,  1) [000070] -----------                            \--*  CNS_INT   ref    null------------ BB04 [???..???) -> BB09 (cond), preds={BB03} succs={BB05,BB09}***** BB04STMT00011 ( ??? ... ??? )     (  7,  6) [000076] -----------                         *  JTRUE     void       (  5,  4) [000075] J------N---                         \--*  LT        int        (  3,  2) [000073] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  1) [000074] -----------                            \--*  CNS_INT   int    0------------ BB05 [???..???) -> BB09 (cond), preds={BB04} succs={BB06,BB09}***** BB05STMT00012 ( ??? ... ??? )     (  9, 11) [000081] ---X-------                         *  JTRUE     void       (  7,  9) [000080] J--X---N---                         \--*  LT        int        (  5,  4) [000079] ---X-------                            +--*  ARR_LENGTH int        (  3,  2) [000078] -----------                            |  \--*  LCL_VAR   ref    V00 arg0              (  1,  4) [000077] -----------                            \--*  CNS_INT   int    0x12345------------ BB06 [004..00B) -> BB13 (cond), preds={BB05,BB07} succs={BB07,BB13}***** BB06STMT00002 ( 0x004[E-] ... 0x009 )               [000013] ----G+-----                         *  JTRUE     void                 [000012] N---G+-N-U-                         \--*  EQ        int                  [000034] ----G+-N---                            +--*  COMMA     int                  [000026] -----+-----                            |  +--*  NOP       void                 [000035] n---G+-----                            |  \--*  IND       int                  [000033] -----+-----                            |     \--*  ARR_ADDR  byref int[]               [000032] -----+-----                            |        \--*  ADD       byref                [000023] -----+-----                            |           +--*  LCL_VAR   ref    V00 arg0                        [000031] -----+-----                            |           \--*  ADD       long                 [000029] -----+-----                            |              +--*  LSH       long                 [000027] -----+---U-                            |              |  +--*  CAST      long <- uint               [000024] -----+-----                            |              |  |  \--*  LCL_VAR   int    V01 loc0                        [000028] -----+-N---                            |              |  \--*  CNS_INT   long   2               [000030] -----+-----                            |              \--*  CNS_INT   long   16               [000011] -----+-----                            \--*  CNS_INT   int    42------------ BB07 [00D..019) -> BB06 (cond), preds={BB06} succs={BB08,BB06}***** BB07STMT00003 ( 0x00D[E-] ... 0x010 )               [000018] -A---+-----                         *  ASG       int                  [000017] D----+-N---                         +--*  LCL_VAR   int    V01 loc0                        [000016] -----+-----                         \--*  ADD       int                  [000014] -----+-----                            +--*  LCL_VAR   int    V01 loc0                        [000015] -----+-----                            \--*  CNS_INT   int    1***** BB07STMT00001 ( 0x011[E-] ... 0x017 )     (  7,  9) [000006] -----------                         *  JTRUE     void       (  5,  7) [000005] J------N---                         \--*  LT        int        (  3,  2) [000003] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  4) [000004] -----------                            \--*  CNS_INT   int    0x12345------------ BB08 [???..???) -> BB12 (always), preds={BB07} succs={BB12}------------ BB09 [???..???), preds={BB03,BB04,BB05} succs={BB10}------------ BB10 [004..00B) -> BB13 (cond), preds={BB09,BB11} succs={BB11,BB13}***** BB10STMT00007 ( 0x004[E-] ... ??? )               [000042] ---XGO-----                         *  JTRUE     void                 [000043] N--XGO-N-U-                         \--*  EQ        int                  [000044] ---XGO-----                            +--*  COMMA     int                  [000045] ---X-O-----                            |  +--*  BOUNDS_CHECK_Rng void                 [000046] -----------                            |  |  +--*  LCL_VAR   int    V01 loc0                        [000047] ---X-------                            |  |  \--*  ARR_LENGTH int                  [000048] -----------                            |  |     \--*  LCL_VAR   ref    V00 arg0                        [000049] n---GO-----                            |  \--*  IND       int                  [000050] -----O-----                            |     \--*  ARR_ADDR  byref int[]               [000051] -----------                            |        \--*  ADD       byref                [000052] -----------                            |           +--*  LCL_VAR   ref    V00 arg0                        [000053] -----------                            |           \--*  ADD       long                 [000054] -----------                            |              +--*  LSH       long                 [000055] ---------U-                            |              |  +--*  CAST      long <- uint               [000056] -----------                            |              |  |  \--*  LCL_VAR   int    V01 loc0                        [000057] -------N---                            |              |  \--*  CNS_INT   long   2               [000058] -----------                            |              \--*  CNS_INT   long   16               [000059] -----------                            \--*  CNS_INT   int    42------------ BB11 [00D..019) -> BB10 (cond), preds={BB10} succs={BB12,BB10}***** BB11STMT00008 ( 0x00D[E-] ... ??? )               [000060] -A---------                         *  ASG       int                  [000061] D------N---                         +--*  LCL_VAR   int    V01 loc0                        [000062] -----------                         \--*  ADD       int                  [000063] -----------                            +--*  LCL_VAR   int    V01 loc0                        [000064] -----------                            \--*  CNS_INT   int    1***** BB11STMT00009 ( 0x011[E-] ... ??? )     (  7,  9) [000065] -----------                         *  JTRUE     void       (  5,  7) [000066] J------N---                         \--*  LT        int        (  3,  2) [000067] -----------                            +--*  LCL_VAR   int    V01 loc0              (  1,  4) [000068] -----------                            \--*  CNS_INT   int    0x12345------------ BB12 [019..01B) (return), preds={BB01,BB08,BB11} succs={}***** BB12STMT00005 ( 0x019[E-] ... 0x01A )               [000022] -----+-----                         *  RETURN    int                  [000037] -----+-----                         \--*  CNS_INT   int    0------------ BB13 [00B..00D) (return), preds={BB06,BB10} succs={}***** BB13STMT00004 ( 0x00B[E-] ... 0x00C )               [000020] -----+-----                         *  RETURN    int                  [000036] -----+-----                         \--*  CNS_INT   int    1-------------------------------------------------------------------------------------------------------------------

3.BB块分析通过去掉的边界检查,进行的优化之后。新增了7个BB块,总共有13个BB块。那么这些BB干嘛的呢?实际上就是为了去掉边界检查(因为在for循环里,每次都要判断),而确保内存array[i]在正确内存范围内。逐一来看下:BB01:

if(i>=0x12345)判断索引是否大于循环最大值

BB02

BB03

if(array==null) //这里是判断数组的地址是否等于0

BB04

if(i<0)判断索引是否小于0

BB05

if(array.length<0x12345)判断数组长度是否小于循环最大数0x12345

BB06

if(array[i]==42)

BB07

i=i+1索引自增

BB08

BB09

BB10

if(i

BB11

i=i+1

BB12

return 0

BB02

return 1

它实际逻辑是:

if(i<0x12345 && array!= null && i>0 && array.Length >= 0x12345 )//再去掉边界检查之后的优化里,这进行大量的检查,确保array[i],在正确内存范围内。{    for (int i = 0; i < 0x12345; i++)    {        if (array[i] == 42) 不检查边界,因为上面的if检查过了        {            return true;        }    }}else  //如果上面的if有一个条件不符合,则进行边界检查。优化不成功{   for (int i = 0; i < 0x12345; i++)    {        if (array[i] == 42) 这里需要边界检查也就是BOUNDS_CHECK_Rng        {            return true;        }    }}
结尾

作者:江湖评谈欢迎关注公众号,第一时间首发分享技术文章。

标签:

延伸阅读

推荐阅读

.Net8顶级技术:边界检查之IR解析(二)

前言IR技术应用在各个编程语言当中,它属于JIT的核心部分,确实有点点麻烦。但部分基本明了。本篇通过 Net

热议:大众和华为,三番五次搞暧昧

大众和华为,三番五次搞暧昧未来双方成功牵手也不会让人意外。毕竟,要允许一些事情发生。软件问题一直是大

“价保”等京东首创服务成电商标配_当前滚动

继首创“晚8点”之后,京东今年618全面让利消费者,围绕低价在全行业掀起新一轮变革。今年也是京东物流211

“加入老年旅游团,我被70多岁大爷调侃体力不行”

【民生调查局】编者按:这里是民生调查局,见人所未见,调查民生之变。关注你想关注的、你没关注的,调查你

正宗麻辣拌的做法及配料_麻辣拌的做法及配料_焦点热议

1、主料:蟹味菇50克,海带100克,菠菜50克,金针菇50克,香肠1根,鱼丸100克,粉条(干)50克辅料:虾50克,

商务部新闻发言人就美国与中国台湾地区完成“美台21世纪贸易倡议”第一部分协议谈判答记者问 每日简讯

上证报中国证券网讯据商务部5月23日消息,商务部新闻发言人就美国与中国台湾地区完成“美台21世纪贸易倡议

@乡亲们:下个月,国家医疗队要来家门口了!

国家卫健委近日发出通知,将以医疗服务能力薄弱地区为重点,派出国家医疗队开展巡回医疗工作。国家医疗队的

专家:十年内我国青贮玉米种植面积或达到1亿亩|消息

2023年中央一号文件提出“大力发展青贮饲料”,我国目前青贮饲料发展如何?有何不足需要改进?5月22日,第

16市全部设立未保机构!山东构建“六位一体”未成年人保护体系-环球速读

未成年人是祖国的未来、民族的希望,关爱保护未成年人是全社会的共同责任。5月23日上午,山东省政府新闻办

最新快讯!又要起飞!绍兴气温直冲35℃

绍兴早间还是凉凉的各地的最低气温仅在15℃上下白天在阳光的助力下气温稳步上扬预计最高气温可达25℃天气趋

世界微动态丨乳戏王黑魔法少女_乳戏王

乳戏王黑魔法少女,乳戏王这个很多人还不知道,现在让我们一起来看看吧!1、Q397537675收到再采纳。本文到此分享

焦点滚动:三款配色惊艳全场!iQOO Neo8系列新机亮相

今日19:00,iQOO新品发布会如期而至,iQOONeo8系列新机正式亮相,iQOONeo8系列在秉承着热血酷玩属性,推出

世界快报:超过7000万用户订阅了Reliance Jio Prime会员资格

电信公司RelianceJio正在获得用户的支持。截至目前,已有7000多万人订阅了Jio的主要会员。如果你看看这些

伊利召开“ESG与社会价值论坛”,发布《WISH2030美好宣言》

5月22日是“国际生物多样性日”,伊利集团在呼和浩特隆重举行“伊利集团ESG与社会价值论坛暨伊利集团ESG‘

【环球热闻】威海广泰:收到泰国AOTGA的采购订单

  上证报中国证券网讯(记者骆民)威海广泰公告,公司近日收到泰国AOTGROUNDAVATIONSERICESCO LTD 的采购

【天天报资讯】国泰航空再回应空乘歧视非英语旅客:已停飞,三日内公布处理结果

就有关旅客在5月21日国泰航班CX987上的经历,引起大家的广泛关注,我们再次郑重道歉。我们高度重视此事件,

港股餐饮板块午后集体走低 海伦司一度跌超7%

截至发稿,海伦司报9 22港元,跌超7%。

先锋基金首席信息官刘冬离任

先锋基金首席信息官刘冬离任---中国经济网北京5月23日讯今日,先锋基金管理有限公司发布高级管理人员变更公

我国数字基础设施规模能级大幅提升 算力规模位居世界第二 环球快播

据中国网信网消息,5月23日,国家互联网信息办公室发布《数字中国发展报告(2022年)》(以下简称《报告》)显

零食量贩店冲击休食行业?从底层逻辑看良品铺子们为何不慌不忙

中宏网股票5月23日电一则公告,再次引发业界对于休闲食品商业模式的广泛讨论。近日,良品铺子披露,持股股

突发涨停潮!一则大消息 这概念大爆发!又一巨头宣布裁员!

今天的市场相对平淡,A股三大指数震荡调整。截至上午收盘,沪指跌0 58%,深成指跌0 12%,创业板指跌0 21%。

天孚通信董秘回复:公司产品广泛应用于电信通信、数据中心、光纤连接和汽车辅助驾驶用激光雷达等领域

天孚通信(300394)05月23日在投资者关系平台上答复了投资者关心的问题。

每日报道:消费活力 持续释放

据了解,汇嘉时代广场北京路店通过引进新店、开展多种促销活动,集聚商圈人气、提振消费信心,满足顾客追求

热推荐:报考驾照遭拒,啥情况?5年前交通违法一直未处理

扬子晚报网5月23日讯(记者郭一鹏通讯员夏文娟)5年前因未取得机动车驾驶证驾驶摩托车,结果被交警查获,可

Meta本周将启动新一轮裁员

品玩5月22日讯,据界面新闻报道,Meta本周将启动新一轮大型裁员,预计将瞄准业务部门。Meta全球事务总裁Nic

博时基金观点:美国经济、消费需求依然稳定 通胀降温速度偏慢-热点聚焦

宏观经济方面,美国4月零售销售环比较强劲。美国4月零售销售环比0 4%,低于预期0 8%,前值为-0 7%。核心零

《福建省“十四五”科普事业发展规划》公布 力争2025年公民具备科学素质的比例超过16% 全球快播

力争2025年我省公民具备科学素质的比例超过16%,科普创新驱动成效显著,科普实力和创新能力大幅跃升,科学

世界资讯:党的二十大精神在警营|“校长”是假!骗你是真

近日,农安县局烧锅派出所接到鲁某锋报案称,其被朋友王某军以介绍装修工程项目的名义骗走35万余元,请求民

qq被盗如何紧急冻结账号_qq被盗

1、1 您可以修改带密码保护的QQ密码。2、如果您的号码在密码丢失时受到密码保护,请登录腾讯QQ安全中心重置

同力股份:5月22日获融资买入7.41万元_全球观速讯

同花顺数据中心显示,同力股份5月22日获融资买入7 41万元,融资偿还25 66万元,当前融资余额140 15万元,占

猜您喜欢

Copyright ©  2015-2022 南极服装网版权所有  备案号:粤ICP备2022077823号-13   联系邮箱: 317 493 128@qq.com