【问题标题】:How to create, handle, and destroy JS::Heap<T> objects in Spidermonkey?如何在 Spidermonkey 中创建、处理和销毁 JS::Heap<T> 对象?
【发布时间】:2015-02-08 05:14:01
【问题描述】:

使用 蜘蛛猴 24、38、45

Spidermonkey documentation 说:“堆上的 GC 事物指针必须包装在 JS::Heap 中。唯一的例外是如果它们作为根添加到 JS_AddRoot() 函数或 JS::PersistentRooted 类中,但除非确实有必要,否则不要这样做。JS::Heap 指针也必须继续以正常方式进行跟踪,此处不做介绍。” p>

在这种情况下,追踪到底意味着什么?以下代码是否缺少某些内容?

struct Foo
{
   Foo(JS::HandleObject bar) : _bar(bar) {}  // Does that root bar?
   ~Foo() {_bar = nullptr;}                  // Does that release memory?

   JS::Heap<JSObject*>  _bar;
};

Foo *create(JSContext *jscontext, JSObject *parent)
{
   JS::RootedObject bar(jscontext, JS_NewObject(jscontext, &SOME_CLASS, NULL, parent));
   return new Foo(bar);
}

我需要添加“跟踪”吗?当 bar 对象存储在 Foo 中时,我是否需要 root bar 对象?我应该使用 JS_AddRoot() 函数来根栏而不是使用堆吗?

【问题讨论】:

    标签: javascript memory-management garbage-collection spidermonkey


    【解决方案1】:

    JS::Heap&lt;T&gt; 用于驻留在堆上的数据结构。跟踪确实是一个要求。如果没有它,GC 可能会确定您的对象无法访问或重新定位它而不更新您的 JS::Heap&lt;T&gt; 句柄。

    在 spidermonkey 中跟踪对象很简单。您需要使用 JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data) 请求额外的 GC 根跟踪器。 JSTraceDataOp 是一个带有接口void traceOp(JSTracer* trc, void* data) 的函数指针。在您的函数中,您必须调用各种 JS_Call&lt;T&gt;Tracer(在 Tracer.h 中定义)方法传递跟踪器和您的对象。此外,您应该根据需要致电JS_TraceChildren

    使用您的示例,添加跟踪器可能如下所示。

    Foo* ref = create(cx, nullptr);
    
    void trace_foos(JSTracer* tracer, void* data) {
       JS_CallHeapObjectTracer(tracer, &(ref->_bar), "foo");
    }
    
    JS_AddExtraGCRootsTracer(rt, trace_foos, nullptr);
    

    每当 GC 运行时,您的跟踪回调就会运行,您应该遍历您的对象图并随时跟踪 GC。

    至于你们cmets中的问题-

       Foo(JS::HandleObject bar) : _bar(bar) {}  // Does that root bar?
    

    bar 已经通过Foo* create 中的JS::RootedObject 条在堆栈中植根。 Heap&lt;T&gt; 句柄不是根 - 这就是为什么必须跟踪它们。只要create 返回,对象就不再是根。

      ~Foo() {_bar = nullptr;}                  // Does that release memory?
    

    没有。 _bar 只是 JS::Heap&lt;T&gt; 句柄的一个实例。它指向的东西将在随后的循环中被垃圾收集。

    【讨论】:

    • 注意:我相信JS::TraceEdge应该在最新版本的SM中使用,而不是现在不推荐使用的JS_CallObjectTracer。 (和JSContext * 而不是JSRuntime *
    【解决方案2】:

    根据 jwilm 的回答,这里有一个 Foo 类实现的示例。

    void trace_obj(JSTracer* tracer, void* data)
    {
        JS_CallObjectTracer(tracer, (JS::Heap<JSObject*>*)data, "jsobj");
    }
    
    class Foo                                                                                                                                                                             
    {                                                                                                                                                                                     
    public:                                                                                                                                                                               
       Foo(JSRuntime *rt, JS::HandleObject bar)                                                                                                                                           
         : _rt(rt),                                                                                                                                                                        
         _bar(bar)                                                                                                                                                                      
       {                                                                                                                                                                                  
         if (_bar.get())                                                                                                                                                                  
           JS_AddExtraGCRootsTracer(_rt, trace_obj, &_bar);                                                                                                                               
       }                                                                                                                                                                                  
       Foo(Foo const &f)                                                                                                                                           
         : _rt(f._rt),                                                                                                                                                                        
         _bar(f._bar)                                                                                                                                                                      
       {                                                                                                                                                                                  
         if (_bar.get())                                                                                                                                                                  
           JS_AddExtraGCRootsTracer(_rt, trace_obj, &_bar);                                                                                                                               
       }                                                                                                                                                                                  
       ~Foo()                                                                                                                                                                             
       {                                                                                                                                                                                  
         if (_bar.get())                                                                                                    
           JS_RemoveExtraGCRootsTracer(_rt, trace_obj, &_bar);                                                                                 
       }                                                                                                                                                                                  
    
    private:                                                                                                                
       JSRuntime *_rt;                                                                                                                                                                    
       JS::Heap<JSObject*> _bar;                                                                                                                                                          
    };                                                                                                                                                                                    
    

    【讨论】:

    • 注意:我相信JS::TraceEdge应该在最新版本的SM中使用,而不是现在不推荐使用的JS_CallObjectTracer。 (和JSContext * 而不是JSRuntime *
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2011-06-02
    相关资源
    最近更新 更多