【问题标题】:CIL (MSIL) tailcall recursion in instance methods实例方法中的 CIL (MSIL) 尾调用递归
【发布时间】:2012-02-08 23:40:41
【问题描述】:

背景:我正在为一个学校项目编写一个 .NET 编译器(非常类似于 C#)。我目前尝试添加的功能之一是方法内的尾调用递归。

更多信息:在 CIL 中,“this”被传递给实例方法,就好像它只是另一个参数一样。因此,访问静态方法的第一个参数,您将发出 ldarg.0,但访问实例方法的第一个参数,您将发出 ldarg.1,而在实例方法中访问“this”,您将发出 ldarg.0 . (实例方法比我想象的更类似于扩展方法。)

问题:您可以使用starg.0 设置“this”而没有任何副作用吗?

为什么会这样:方法是否是实例方法是通过 MethodBuilder 设置的,它有点像一个黑盒子。尽管“this”看起来就像任何其他参数一样,但据我所知,一些 JIT 编译器会单独跟踪“this”并根据该值更改它们的行为。如果在实例方法中设置“this”有副作用,那么如何避免呢?

【问题讨论】:

  • 虽然这是一个有趣的问题,但我想补充一点,您是在问我认为什么是极端情况:您的问题仅在尾调用不同类实例上的当前方法时才重要。无论如何,不​​可能按照您描述的方式尾调用不同的方法,并且使用相同的 this 尾调用当前方法不需要修改参数 0。

标签: tail-recursion il tail-call-optimization tail-call


【解决方案1】:

您可能想看看how F# implements tail-call

【讨论】:

  • 我也在下面的评论中说过,但我会在这里重复一遍。回想起来,我并没有问我真正的意思,只是如何解决它的症状。这是一个诚实的错误,但我很抱歉我误导了。
【解决方案2】:

您可以将其提取为局部变量。这样你就会知道你可以安全地设置它。 (希望我能正确理解你的问题)

【讨论】:

  • 这并不能解决问题 - 如果您只是发出 starg.0 并假设 JIT 编译器也已更新,则会发生相同的副作用。不过,感谢您的回答。
  • 所以您担心即使您将引用传递给局部变量,JIT 编译器也会跟踪“this”?
  • @aboveyou00 这是一个正确的答案,即使 starg.0 不安全(我不明白为什么会这样,但我不确定),使用额外的变量参数 0 肯定是安全的。
  • 我并不是说 JIT 会在你背后修改 arg.0,我的意思是他们可能不会检查你自己的修改,这可能会以一种微妙的方式影响代码执行。无论如何,Chris Shain 回答了我的问题。请参阅上面的帖子,以及最终生成的 MSDN 页面:OpCodes.TailCall Field
  • @aboveyou00 对于第二部分,OpCodes.TailCall 与您提出的问题没有太大关系。 OpCodes.TailCall 是关于让 .NET 运行时执行尾调用优化(并且为此更改任何参数都是不必要的),而您提出的问题(可能不是您要问的问题)是关于执行尾调用优化的编译器。但是尝试同时实现这两者会很有趣,我很高兴你找到了你正在寻找的东西。
猜你喜欢
  • 2016-03-21
  • 2017-03-05
  • 1970-01-01
  • 2020-07-13
  • 1970-01-01
  • 2019-03-09
  • 2011-05-01
  • 1970-01-01
  • 2010-12-08
相关资源
最近更新 更多