2012-02-08 80 views
3

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

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

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

为什么会出现这样的问题:方法是否是实例方法是通过MethodBuilder设置的,这是一个黑盒子。尽管“this”看起来和其他任何争论一样,但我知道一些JIT编译器会分别跟踪“this”并根据这个值改变它们的行为。如果在实例方法中设置“this”时存在副作用,那么我该如何避免它们?

+0

虽然这是一个有趣的问题,但我想补充一点,你问的是我认为会成为一个特例的情况:只有在不同的类实例上调用当前方法时,您的问题才重要。按照你描述的方式,不同的方式是不可能的,使用相同的'this'来调用当前的方法并不需要修改参数0. – hvd 2012-02-09 00:03:38

回答

2

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

+0

完美!谢谢! – aboveyou00 2012-02-09 00:05:04

+0

有人可以指出相关部分吗? – Stilgar 2012-02-09 00:11:09

+0

我在下面的评论中也是这样说的,但我会在这里重复一遍。回想起来,我没有问我的意思,只是如何解决它的一个症状。这是一个诚实的错误,但是我很抱歉我无论如何都在误导。 – aboveyou00 2012-02-09 00:35:47

1

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

+0

这并不能解决问题 - 将会发生相同的副作用如果你只发出starg.0,并且假定JIT编译器也被更新。不过谢谢你的回答。 – aboveyou00 2012-02-08 23:55:29

+0

@ aboveyou00这是一个正确的答案,即使'starg.0'不安全(我不明白为什么会这样,但我不确定),使用额外的变量代替参数0肯定是必须的注意安全。 – hvd 2012-02-09 00:06:07

+0

所以你担心即使你将引用传递给本地变量,JIT编译器也会跟踪“this”吗? – Stilgar 2012-02-09 00:06:07