GC根源误解?

时间:2012-03-30 06:46:36

标签: c# .net-4.0 garbage-collection

我知道Roots是:

  • 静态字段
  • 方法参数
  • 本地fielfs
  • f-queue,它还包含一个指向“即将被完成”对象的指针
  • cpu registers< = ???

enter image description here

现在让我们谈谈寄存器。

他们可以包含的代码如下:

mov bx, 0034h   ; bx = 52 (stored in 16 bits)
mov cl, bl      ; cl = lower 8-bits of bx
mov eax, ecx
call print_int

等待

如果我没弄错的话,这是实际的代码持有那些staticlocalparameters - 从第一位开始!

那么为什么要写这个 TWICE ? (或从另一个方向?)

为什么要写(例如)

  Foo f = new Foo();

**and also** 

mov bx, 0034h   //<-------- represents the `f` address or something like that 

修改

关于寄存器的问题来自这里: enter image description here

enter image description here

3 个答案:

答案 0 :(得分:2)

寄存器只临时保存变量的值。

例如,当您创建对象并将引用存储在变量中时:

Foo f = new Foo();

发生的事情是调用构造函数,并返回对象的引用。在此阶段,引用仅存在于寄存器中。然后寄存器的内容被复制到变量中,所以现在引用存在于寄存器和变量中。然后寄存器继续并用于其他内容,因此引用仅存在于变量中。


另请注意,不仅寄存器中当前的值是根。每个线程都有自己的一组寄存器,当线程没有运行时,这些寄存器会切换到内存,所有这些寄存器值集也都是根。

答案 1 :(得分:2)

因为JIT编译器可能会优化某些部分而不使用堆栈但直接转到寄存器。

让我们进行方法调用,例如:

object a = new object(), b = new object(), c = new object();
DoSomething(a, b, c);

JIT编译器会尝试将尽可能多的参数放入寄存器rahter,而不是将它们推入堆栈。在X86上本地构建的示例显示:

00000082  push        dword ptr [ebp-10h] 
00000085  mov         ecx,dword ptr [ebp-8] 
00000088  mov         edx,dword ptr [ebp-0Ch] 
0000008b  call        dword ptr ds:[00742078h] 

现在有更复杂的角落情况,考虑数组/对象访问。

答案 2 :(得分:2)

考虑

string sentence = ...
int wordCount = sentence.Split(' ').Length;

String.Split()生成一个数组,必须保持对该语句的(部分)可达。但是没有指向它的变量或参数,优化器很可能将引用保留在寄存器中。

因此必须将CPU(地址)寄存器视为根的一部分。