Changes between Version 6 and Version 7 of JSRootingGuide


Ignore:
Timestamp:
Jun 22, 2014, 12:02:30 AM (10 years ago)
Author:
Yves
Comment:

Adds examples for heap rooting

Legend:

Unmodified
Added
Removed
Modified
  • JSRootingGuide

    v6 v7  
    3939TODO: are they going to remove it from the API? Are there use cases where this rooting approach is superior?
    4040
    41 Characteristics:
     41==== Characteristics:
    4242 * If no RAII approach is used, it can easily cause leaks if the call to Remove*Root() is missing.
    4343 * In some Gecko use cases this can't be used because it can cause cycles and the cycle collector won't know about them (this is not relevant for us because we don't need a cycle collector).
     
    4545 * Add*Root is slow --> What does this mean in practice?
    4646
    47 Guideline:
     47==== Guideline:
    4848 * Try to use the other approaches for the moment. We still have to figure out when/if this approach should be used.
     49
     50
     51==== Example
     52Check the attached main.cpp for a full working example (including the base class).
     53
     54{{{
     55#!c++
     56#ifndef HEAPROOTINGTEST_H_INCLUDED
     57#define HEAPROOTINGTEST_H_INCLUDED
     58
     59using namespace std;
     60
     61class CHeapRootingTest : CTestClassBase
     62{
     63public:
     64       
     65        CHeapRootingTest(JSRuntime* rt, JSContext* cx) : CTestClassBase(rt, cx)
     66        {
     67                m_HeapValue.setObject(*InitObjectInternal());
     68                JS::AddValueRoot(m_cx, &m_HeapValue);
     69        }
     70       
     71        ~CHeapRootingTest()
     72        {
     73                JSAutoRequest rq(m_cx);
     74                JS::RemoveValueRoot(m_cx, &m_HeapValue);
     75        }
     76       
     77        void PrintUsecount()
     78        {
     79                JSAutoRequest rq(m_cx);
     80                if (!m_HeapValue.isObject())
     81                        cerr << "Error: m_HeapValue is not an object!" << endl;
     82               
     83                JS::RootedObject objStack(m_cx, &m_HeapValue.toObject());
     84                PrintUsecountBase(objStack);
     85        }
     86       
     87private:
     88         JS::Heap<JS::Value> m_HeapValue;
     89};
     90
     91#endif // HEAPROOTINGTEST_H_INCLUDED
     92
     93}}}
    4994
    5095=== Using JS::Heap<T> in combination with custom tracers ===
     
    5398Note: There are other ways to add a specified trace function (I haven't tested those yet).
    5499
    55 Characteristics:
     100==== Characteristics:
    56101 * Obviously it's faster to add (and later remove) one function that gets called during GC and loops over many objects than adding (and removing) many objects to the GC root set in a loop.
    57102 * Less memory overhead because storing a pointer to a trace function requires less memory than storing a large number of pointers to GC things.
    58103
    59 Guideline:
     104==== Guideline:
    60105 * This approach should be used if large numbers of GC things need to be rooted.
    61106
     107==== Example
     108Check the attached main.cpp for a full working example (including the base class).
     109
     110{{{
     111#!c++
     112#ifndef HEAPROOTINGTEST_H_INCLUDED
     113#define HEAPROOTINGTEST_H_INCLUDED
     114
     115class CHeapRootingTest : CTestClassBase
     116{
     117public:
     118       
     119        static void Trace(JSTracer *trc, void *data)
     120        {
     121                reinterpret_cast<CHeapRootingTest*>(data)->TraceMember(trc);
     122        }
     123       
     124        void TraceMember(JSTracer *trc)
     125        {
     126                // The JS_Call<T>Tracer family of functions (those without the "Heap" in the name) will be deprecate in the future.
     127                JS_CallHeapValueTracer(trc, &m_HeapValue, "m_HeapValue");
     128        }
     129
     130        CHeapRootingTest(JSRuntime* rt, JSContext* cx) : CTestClassBase(rt, cx)
     131        {
     132                m_HeapValue.setObject(*InitObjectInternal());
     133                JS_AddExtraGCRootsTracer(rt, CHeapRootingTest::Trace, this);
     134        }
     135       
     136        ~CHeapRootingTest()
     137        {
     138                JS_RemoveExtraGCRootsTracer(m_rt, CHeapRootingTest::Trace, this);
     139        }
     140       
     141        void PrintUsecount()
     142        {
     143                JSAutoRequest rq(m_cx);
     144                if (!m_HeapValue.isObject())
     145                        cerr << "Error: m_HeapValue is not an object!" << endl;
     146                JS::RootedObject objStack(m_cx, &m_HeapValue.toObject());
     147                PrintUsecountBase(objStack);
     148        }
     149       
     150private:
     151         JS::Heap<JS::Value> m_HeapValue;
     152};
     153
     154#endif // HEAPROOTINGTEST_H_INCLUDED
     155}}}
     156
    62157=== Using JS::!PersistentRooted<T> ===
    63158
    64 Characteristics:
     159==== Characteristics:
    65160 * This type both keeps the reference to the GC thing valid when it gets moved and it protects it against garbage collection.
    66161 * Costs a small memory and CPU performance overhead (stores GC things to be rooted in a linked list internally).
    67162 * It's obviously easier to use, the code looks cleaner and it's less error prone.
    68163
    69 Guideline:
     164==== Guideline:
    70165 * This approach should be used for small numbers of objects that don't get rooted and unrooted often.
    71166 
     167==== Example
     168Check the attached main.cpp for a full working example (including the base class).
     169
     170{{{
     171#!c++
     172#ifndef HEAPROOTINGTEST_H_INCLUDED
     173#define HEAPROOTINGTEST_H_INCLUDED
     174
     175class CHeapRootingTest : CTestClassBase
     176{
     177public:
     178       
     179        CHeapRootingTest(JSRuntime* rt, JSContext* cx) : m_HeapValue(cx), CTestClassBase(rt, cx)
     180        {
     181                m_HeapValue = JS::ObjectValue(*InitObjectInternal());
     182        }
     183       
     184        void PrintUsecount()
     185        {
     186                if (!m_HeapValue.get().isObject())
     187                        cerr << "Error: m_HeapValue is not an object!" << endl;
     188                JS::RootedObject objStack(m_cx, &m_HeapValue.get().toObject());
     189                PrintUsecountBase(objStack);
     190        }
     191       
     192private:
     193         JS::PersistentRootedValue m_HeapValue;
     194};
     195
     196#endif // HEAPROOTINGTEST_H_INCLUDED
     197}}}
    72198
    73199== Testing Rooting ==