c# - .NET 3.5 JIT 在运行应用程序时不起作用

标签 c# .net-3.5 jit

以下代码在 Visual Studio 内部运行版本和在 Visual Studio 外部运行版本时提供不同的输出。我正在使用 Visual Studio 2008 并以 .NET 3.5 为目标。我也尝试过 .NET 3.5 SP1。

在 Visual Studio 之外运行时,JIT 应该启动。要么 (a) 我遗漏了 C# 发生的一些微妙的事情,要么 (b) JIT 实际上出错了。我怀疑 JIT 会出错,但我已经没有其他可能性了......

在 Visual Studio 中运行时的输出:

    0 0,
    0 1,
    1 0,
    1 1,

在 Visual Studio 之外运行发布时的输出:

    0 2,
    0 2,
    1 2,
    1 2,

这是什么原因?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test
{
    struct IntVec
    {
        public int x;
        public int y;
    }

    interface IDoSomething
    {
        void Do(IntVec o);
    }

    class DoSomething : IDoSomething
    {
        public void Do(IntVec o)
        {
            Console.WriteLine(o.x.ToString() + " " + o.y.ToString()+",");
        }
    }

    class Program
    {
        static void Test(IDoSomething oDoesSomething)
        {
            IntVec oVec = new IntVec();
            for (oVec.x = 0; oVec.x < 2; oVec.x++)
            {
                for (oVec.y = 0; oVec.y < 2; oVec.y++)
                {
                    oDoesSomething.Do(oVec);
                }
            }
        }

        static void Main(string[] args)
        {
            Test(new DoSomething());
            Console.ReadLine();
        }
    }
}

最佳答案

这是一个 JIT 优化器错误。它正在展开内部循环但没有正确更新 oVec.y 值:

      for (oVec.x = 0; oVec.x < 2; oVec.x++) {
0000000a  xor         esi,esi                         ; oVec.x = 0
        for (oVec.y = 0; oVec.y < 2; oVec.y++) {
0000000c  mov         edi,2                           ; oVec.y = 2, WRONG!
          oDoesSomething.Do(oVec);
00000011  push        edi  
00000012  push        esi  
00000013  mov         ecx,ebx 
00000015  call        dword ptr ds:[00170210h]        ; first unrolled call
0000001b  push        edi                             ; WRONG! does not increment oVec.y
0000001c  push        esi  
0000001d  mov         ecx,ebx 
0000001f  call        dword ptr ds:[00170210h]        ; second unrolled call
      for (oVec.x = 0; oVec.x < 2; oVec.x++) {
00000025  inc         esi  
00000026  cmp         esi,2 
00000029  jl          0000000C 

当您让 oVec.y 增加到 4 时,错误消失了,因为调用太多而无法展开。

一种解决方法是:

  for (int x = 0; x < 2; x++) {
    for (int y = 0; y < 2; y++) {
      oDoesSomething.Do(new IntVec(x, y));
    }
  }

更新:2012 年 8 月重新检查,此错误已在版本 4.0.30319 抖动中修复。但是在v2.0.50727 中仍然存在抖动。这么长时间后,他们似乎不太可能在旧版本中修复此问题。

关于c# - .NET 3.5 JIT 在运行应用程序时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2056948/

相关文章:

c# - 无法将 .net 3.5 网站添加到 IIS Express

java - 如何模拟JIT优化来查看优化后的字节码?

c# - 将这种字符串解析为 DateTime - "Friday 22nd March 2013"(C#)

c# - ObjectSet的Where()方法和内存

c# - 上传文件到数据库

c# - 尝试让一个对象查看 Unity 中的另一个对象

string - 使用 .NET 3.5 查找字符串中的第一个数字

c# - 以编程方式隐藏/禁用/删除/shootintheface office 2007 功能区

java - Hotspot JIT 编译器完成的任何指令重新排序是否可以重现?

c# - 有没有办法让 .Net JIT 或 C# 编译器优化掉空的 for 循环?