rednaxelafx的Cheney算法的伪代码。如果不用forwarding的话,维护一个旧地址到新地址的映射也可以。
其中重点部分:
1 void Heap::collect() { 2 // The from-space contains objects, and the to-space is empty now. 3 4 address scanned = _to_space->bottom(); 5 6 // scavenge objects directly referenced by the root set 7 foreach (Object** slot in ROOTS) { 8 process_reference(slot); 9 } 10 11 // breadth-first scanning of object graph 12 while (scanned < _to_space->top()) { 13 Object* parent_obj = (Object*) scanned; 14 foreach (Object** slot in parent_obj->obejct_fields()) { 15 process_reference(slot); 16 // note: _to_space->top() moves if any object is newly copied 17 // into to-space. 18 } 19 scanned += parent_obj->size(); 20 } 21 22 // Now all live objects will have been evacuated into the to-space, 23 // and we don't need the data in the from-space anymore. 24 25 swap_spaces(); 26 }
Cheney算法的简单优雅之处来自它通过隐式队列来实现广度优先遍历,但它的缺点之一却也在此:广度优先的拷贝顺序使得GC后对象的空间局部性(memory locality)变差了。但是如果要改为真的深度优先顺序就会需要一个栈,无论是隐式(通常意味着递归调用)或者是显式。
HotSpot Seial GC => rednaxelafx的Cheney算法伪代码
* saved mark => scanned
* FastScanClosure => process_reference()
* GenCollectedHeap::gen_process_strong_roots()、SharedHeap::process_strong_roots() => 遍历根集合的循环逻辑
* FastEvacuateFollowersClosure => 遍历扫描队列的循环
* oopDesc::oop_iterate() => 遍历对象的引用类型字段的循环,Object::object_fields()
* DefNewGeneration::copy_to_survivor_space() => 拷贝对象的逻辑,Heap::evacuate()
ParalleScavenge总体过程虽然也是这样,但是因为多线程模型细节复杂很多。除strong reference之外,其他的soft,weak,phantom等reference也要处理。
rednaxelafx的完整回答
http://hllvm.group.iteye.com/group/topic/39376
其他Cheney算法的概述
https://en.wikipedia.org/wiki/Cheney%27s_algorithm
http://www.cs.umd.edu/class/fall2002/cmsc631/cheney/cheney.html