【问题标题】:C++ precise garbage collector using clang/llvm?使用 clang/llvm 的 C++ 精确垃圾收集器?
【发布时间】:2012-04-28 07:04:17
【问题描述】:

好的,所以我想用 C++ 编写一个精确的“标记和清除”垃圾收集器。我希望做出一些可以帮助我的决定,因为我的所有指针都将包装在一个“RelocObject”中,并且我将为堆提供一个内存块。这看起来像这样:

// This class acts as an indirection to the actual object in memory so that it can be      
// relocated in the sweep phase of garbage collector
class MemBlock
{
public:
    void* Get( void ) { return m_ptr; }

private:
    MemBlock( void ) : m_ptr( NULL ){}

    void* m_ptr;
};

// This is of the same size as the above class and is directly cast to it, but is     
// typed so that we can easily debug the underlying object
template<typename _Type_>
class TypedBlock
{
public:
    _Type_* Get( void ) { return m_pObject; }

private:
    TypedBlock( void ) : m_pObject( NULL ){}

    // Pointer to actual object in memory
    _Type_* m_pObject;
};

// This is our wrapper class that every pointer is wrapped in 
template< typename _Type_ >
class RelocObject
{
public:

    RelocObject( void ) : m_pRef( NULL ) {}

    static RelocObject New( void )
    {
        RelocObject ref( (TypedBlock<_Type_>*)Allocator()->Alloc( this, sizeof(_Type_), __alignof(_Type_) ) );
        new ( ref.m_pRef->Get() ) _Type_();
        return ref;
    }

    ~RelocObject(){}

    _Type_*     operator->  ( void ) const 
    { 
        assert( m_pRef && "ERROR! Object is null\n" ); 
        return (_Type_*)m_pRef->Get(); 
    }

    // Equality
    bool operator ==(const RelocObject& rhs) const { return m_pRef->Get() == rhs.m_pRef->Get(); }
    bool operator !=(const RelocObject& rhs) const { return m_pRef->Get() != rhs.m_pRef->Get(); }

    RelocObject&    operator=   ( const RelocObject& rhs ) 
    {
        if(this == &rhs) return *this;
        m_pRef = rhs.m_pRef;
        return *this; 
    }

private:

    RelocObject( TypedBlock<_Type_>* pRef ) : m_pRef( pRef ) 
    {
        assert( m_pRef && "ERROR! Can't construct a null object\n");
    }

    RelocObject*    operator&   ( void ) { return this; }
    _Type_&     operator*   ( void ) const { return *(_Type_*)m_pRef->Get(); }

    // SS: 
    TypedBlock<_Type_>* m_pRef;
};

// We would use it like so...
typedef RelocObject<Impl::Foo> Foo;

void main( void )
{
    Foo foo = Foo::New();
}

因此,为了在“RelocObject::New”中分配时找到“根”RelocObjects,我将 RelocObject 的“this”指针传递给分配器(垃圾收集器)。然后分配器检查“this”指针是否在堆的内存块范围内,如果是,那么我可以假设它不是根。

因此,当我想使用位于每个子对象内的零个或多个 RelocObjects 从根跟踪子对象时,问题就出现了。

我想使用“精确”方法在类(即子对象)中找到 RelocObjects。我可以使用反射方法并让用户注册他或她的 RelocObjects 在每个类中的位置。但是,这很容易出错,所以我想自动执行此操作。

因此,我希望在编译时使用 Clang 在类中查找 RelocObjects 的偏移量,然后在程序启动时加载此信息,并在垃圾收集器的标记阶段使用它来跟踪并标记子对象。

所以我的问题是 Clang 可以提供帮助吗?我听说您可以在编译期间使用其编译时挂钩收集各种类型信息。如果是这样,我应该在 Clang 中寻找什么,即有没有做这种事情的例子?

明确一点:我想使用 Clang 在 FooB 中自动查找“Foo”(这是 RelocObject 的 typedef)的偏移量,而无需用户提供任何“提示”,即他们只写:

class FooB
{
public:
    int m_a;
    Foo m_ptr;
};

提前感谢您的帮助。

【问题讨论】:

  • 那么你打算如何处理一个在一个变体中包含一个指针并且在另一个变体中被一个 int 覆盖的联合?语言设计似乎阻止了“精确”识别指针的能力。
  • ...如果您要实现这样的垃圾收集器,我希望您希望使用 Clang 生成所有与 GC 相关的代码(例如,分配和释放 [例如,您可以'不要摆脱 C++ 中的析构函数]),并且它已经为该语言的其余部分生成了代码。在 Clang 中,您应该可以访问此字段偏移数据(我不是 Clang 专家,所以我没有详细信息)。但是你听起来好像你想在 Clang 之外做这一切。为什么?
  • @Ira:我不太在意诸如 union tbh 之类的“很高兴拥有”功能。我能够限制我的用户的使用模式。本质上,我有纯 C++ 的模块(它们可以做任何他们想做的事情)和受约束的模块,即它们不允许使用原始指针:确保它们可以使用它们,但如果它们可能会破坏它们做。想想托管和非托管 C++:两者各有利弊。
  • @Ira:我正在让我的 Impl:: 类有私有的 ctors 和 dtors,但与垃圾收集器是朋友。我真的不希望 Clang 生成代码只是关于我的课程的信息。实际上我不想在 Clang 之外做这件事,对不起,如果我给人的印象是:我只是想让 Clang 在编译过程中转储这些信息。也许我需要稍微改一下我的问题!

标签: c++ garbage-collection clang


【解决方案1】:

每当RelocObject 被实例化时,它的地址可以与sizeof(*derivedRelocObject) 一起记录在RelocObject 所有权数据库中,该数据库将立即识别出哪个Foo 属于哪个FooB。你不需要 Clang。此外,由于Foo 将在FooB 之后不久创建,因此您的所有权数据库系统可以非常简单,因为“我已经创建,这里是我的地址和大小”的顺序调用将显示在它拥有的 RelocObject 实例之前直接拥有 RelocObject 记录。

每个RelocObject 都有一个ownership_been_declared 标志初始化为假,在第一次使用时(这将在构造函数完成之后,因为在构造函数中不应该做任何实际工作),所以当这些新创建的对象中的任何一个第一次使用它请求数据库更新它的所有权,数据库通过它的记录地址队列并可以识别哪些对象属于哪个,从它的列表中清除一些,将它们的ownership_been_declared标志设置为true,你将拥有偏移量也可以(如果您仍然需要它们)。


附言如果您愿意,我可以分享我多年前编写的增量垃圾收集器的代码,这可能会对您有所帮助。

【讨论】:

  • 首先感谢您的详细回复。我想沿着偏移路线走,因为我不希望为类的每个实例存储指针的开销。我只想为每个类生成一个偏移函数,即 GetChildren(this)。我对您如何使所有权数据库保持简单很感兴趣,因为您肯定需要至少一个链接列表和一个嵌入其中的空闲列表,因为随机创建/删除命令(我不同意这很简单,顺便说一句只是我感兴趣在组织该数据库时可能有的任何技巧)。
  • @user176168 对延迟响应表示歉意。我创建了一个分区集结构(基本上是一个允许您将对象分配和重新分配给分区的结构)。我有 5 个分区,白色、黑色、新建、删除和灰色 (IIRC)。 Reference 结构存储了两个引用。一个是在每个标记周期开始时冻结的引用,另一个将被主动更新。
猜你喜欢
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
相关资源
最近更新 更多