Tiger垃圾收集器的实现

来源:互联网 发布:桂纶镁 戴立忍 知乎 编辑:程序博客网 时间:2024/05/29 08:46

配合实验文档Lab4

先解释文档里面的三个名词。

Memory GC Maps

Call Stack and GC Stack

Class GC Maps


       Memory GC Maps 是为了记录变量是否指向堆上。显然,只有指向堆上,才有必要回收。这里因为Tiger没有static的变量,所以我们执行一个方法的时候,参数列表里面的变量是唯一引用外面变量的地方。问题是,参数列表里面可能有int,可能有struct*,如何分辨哪个是需要回收的呢??我们可以看出来,struct*是需要回收的,所以在程序里面需要一种结构记录这种关系。这里我们采用位图法(bit-vector)。显然,没一个方法对应着自己的位图。

      下面举个例子。

http://write.blog.csdn.net/postedit

可以看到这个Doit_doit(struct Doit* this,int n)这个函数,两个参数一个是指向堆上的,一个是int(不是malloc的),所以位图就是"10"。这里之所以才是这种方法是有函数调用规则决定的。

The C calling convention and call stack layout can be well explained by the functionf from theabove exercise. The following figure illustrates thestack layout off on the x86 ISA:

  ----------------------------------------------------------> low address   | arg3 | arg2 | arg1 | this | ret | ebp |  locals?  -----------------------------------------------------------                                        ^                                       ebp
      除此之外,每个方法还有自己的局部变量(locals),这些变量也有可能存在于堆上。所以,针对这个问题,我们也需要一个方式记录方法的那些变量分配到了堆上。这里就又出来了一个结构——frame!

      关于frame在Lab4文档上面介绍的比较详细,这里结合一个具体例子简单说一下。

struct f_gc_frame{  void *prev;                     // dynamic chain, pointing to f's caller's GC frame  char *arguments_gc_map;         // should be assigned the value of "f_arguments_gc_map"  int *arguments_base_address;    // address of the first argument  char *locals_gc_map;            // should be assigned the value of "f_locals_gc_map"  struct A *local1;               // remaining fields are method locals  int local2;  struct C *local3;};

       看上面的例子。右边是java代码,编译之后变为C。可以看到,j这个变量出现在了frame里面。原因是j是一个数组,需要分配到堆上,所以我们这一种变量全都声明的frame里面,到时候通过frame.j访问这个变量指向的数组。因为这个doit方法只有一个这样的局部变量,所以他的locals_gc_map=1。这个locals_gc_map就是记录方法的局部变量里面到底有几个是分配到堆上的。

      到目前位置,方法就搞定了。就可以通过位图记录参数的情况,又有局部变量的记录。


      最后来看看Class。在Class里面也可以声明变量,比如上图里面Class Doit里面的int k和int p。当然,也可以声明数组和对象。这里有个问题需要注意,类跟方法不一样。不论类里面声明的变量是什么类型,都是分配在堆上(需要仔细体会)。如果按照上面的思路,是否可以再用一个frame把类里面的变量分为两类呢??答案是:没必要。方法用frame的原因是为了GC可以找到方法里面的堆变量,而且frame构成的链式栈复合方法调用的顺序。在处理class的时候,我们这采用的方法还是位图法。思路跟上面处理函数参数时是一样的。上图中Class Doit里面声明的两个int型变量,所以位图是“00”。





0 0
原创粉丝点击