Global Metrics
path: .metrics.cognitive.average
old: 0.0
new: 0.08695652173913043
path: .metrics.cognitive.sum
old: 0.0
new: 2.0
path: .metrics.cyclomatic.average
old: 1.0
new: 1.236842105263158
path: .metrics.cyclomatic.sum
old: 9.0
new: 47.0
path: .metrics.halstead.level
old: 0.061952861952861954
new: 0.027791705465224553
path: .metrics.halstead.effort
old: 27586.082713186406
new: 407184.14028473577
path: .metrics.halstead.N2
old: 135.0
new: 607.0
path: .metrics.halstead.volume
old: 1709.0367741502691
new: 11316.341696904052
path: .metrics.halstead.vocabulary
old: 57.0
new: 217.0
path: .metrics.halstead.difficulty
old: 16.141304347826086
new: 35.9819587628866
path: .metrics.halstead.length
old: 293.0
new: 1458.0
path: .metrics.halstead.N1
old: 158.0
new: 851.0
path: .metrics.halstead.bugs
old: 0.30432579693911416
new: 1.8312149051497464
path: .metrics.halstead.estimated_program_length
old: 292.1375977836329
new: 1578.4250163736142
path: .metrics.halstead.time
old: 1532.5601507325782
new: 22621.341126929765
path: .metrics.halstead.purity_ratio
old: 0.9970566477257096
new: 1.082596033178062
path: .metrics.halstead.n1
old: 11.0
new: 23.0
path: .metrics.halstead.n2
old: 46.0
new: 194.0
path: .metrics.nargs.average
old: 2.2857142857142856
new: 0.8695652173913043
path: .metrics.nargs.sum
old: 16.0
new: 20.0
path: .metrics.mi.mi_sei
old: 41.937675826903856
new: -39.65212118668394
path: .metrics.mi.mi_visual_studio
old: 36.04111788378195
new: 0.20954296135882763
path: .metrics.mi.mi_original
old: 61.63031158126714
new: 0.35831846392359523
path: .metrics.nom.functions
old: 7.0
new: 23.0
path: .metrics.nom.total
old: 7.0
new: 23.0
path: .metrics.loc.blank
old: 8.0
new: 446.0
path: .metrics.loc.ploc
old: 51.0
new: 341.0
path: .metrics.loc.cloc
old: 10.0
new: 176.0
path: .metrics.loc.sloc
old: 69.0
new: 963.0
path: .metrics.loc.lloc
old: 23.0
new: 48.0
path: .metrics.nexits.average
old: 0.7142857142857143
new: 0.6521739130434783
path: .metrics.nexits.sum
old: 5.0
new: 15.0
Spaces Data
Minimal test - lines (96, 120)
path: .spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 1.7818257188470974
new: 0.6060101260867115
path: .spaces[0].spaces[5].metrics.halstead.bugs
old: 0.04245684983318792
new: 0.19967269424074788
path: .spaces[0].spaces[5].metrics.halstead.length
old: 40.0
new: 188.0
path: .spaces[0].spaces[5].metrics.halstead.vocabulary
old: 21.0
new: 29.0
path: .spaces[0].spaces[5].metrics.halstead.n2
old: 11.0
new: 19.0
path: .spaces[0].spaces[5].metrics.halstead.level
old: 0.12222222222222222
new: 0.06229508196721311
path: .spaces[0].spaces[5].metrics.halstead.N2
old: 18.0
new: 61.0
path: .spaces[0].spaces[5].metrics.halstead.difficulty
old: 8.181818181818182
new: 16.05263157894737
path: .spaces[0].spaces[5].metrics.halstead.N1
old: 22.0
new: 127.0
path: .spaces[0].spaces[5].metrics.halstead.volume
old: 175.69269691115042
new: 913.3004270839835
path: .spaces[0].spaces[5].metrics.halstead.effort
old: 1437.4857020003217
new: 14660.875276874474
path: .spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 71.27302875388389
new: 113.92990370430176
path: .spaces[0].spaces[5].metrics.halstead.time
old: 79.86031677779565
new: 814.4930709374707
path: .spaces[0].spaces[5].metrics.cyclomatic.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[5].metrics.mi.mi_sei
old: 118.36545937409804
new: 44.16781209758042
path: .spaces[0].spaces[5].metrics.mi.mi_original
old: 110.20561759577762
new: 82.94547425424624
path: .spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 64.44772958817404
new: 48.50612529488084
path: .spaces[0].spaces[5].metrics.nargs.average
old: 3.0
new: 1.0
path: .spaces[0].spaces[5].metrics.nargs.sum
old: 3.0
new: 1.0
path: .spaces[0].spaces[5].metrics.nexits.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[5].metrics.nexits.average
old: 1.0
new: 0.0
path: .spaces[0].spaces[5].metrics.loc.cloc
old: 2.0
new: 0.0
path: .spaces[0].spaces[5].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[5].metrics.loc.sloc
old: 8.0
new: 25.0
path: .spaces[0].spaces[5].metrics.loc.blank
old: 0.0
new: 3.0
path: .spaces[0].spaces[5].metrics.loc.ploc
old: 7.0
new: 22.0
Code
struct TraceCallbackFunc : public TraceCallbacks {
typedef void (*Func)(JS::GCCellPtr aPtr, const char* aName, void* aClosure);
explicit TraceCallbackFunc(Func aCb) : mCallback(aCb) {}
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(nsWrapperCache* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
private:
Func mCallback;
};
Minimal test - lines (58, 58)
path: .spaces[0].spaces[2].metrics.loc.sloc
old: 6.0
new: 1.0
path: .spaces[0].spaces[2].metrics.loc.lloc
old: 4.0
new: 0.0
path: .spaces[0].spaces[2].metrics.loc.ploc
old: 6.0
new: 1.0
path: .spaces[0].spaces[2].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].spaces[2].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].spaces[2].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.level
old: 0.10434782608695652
new: null
path: .spaces[0].spaces[2].metrics.halstead.purity_ratio
old: 1.588308978281823
new: null
path: .spaces[0].spaces[2].metrics.halstead.length
old: 48.0
new: 1.0
path: .spaces[0].spaces[2].metrics.halstead.time
old: 113.9632524762865
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.difficulty
old: 9.583333333333334
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.estimated_program_length
old: 76.2388309575275
new: null
path: .spaces[0].spaces[2].metrics.halstead.N1
old: 25.0
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.N2
old: 23.0
new: 1.0
path: .spaces[0].spaces[2].metrics.halstead.volume
old: 214.05271769459029
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.bugs
old: 0.05381503647043775
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.effort
old: 2051.338544573157
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.n1
old: 10.0
new: 0.0
path: .spaces[0].spaces[2].metrics.halstead.n2
old: 12.0
new: 1.0
path: .spaces[0].spaces[2].metrics.halstead.vocabulary
old: 22.0
new: 1.0
path: .spaces[0].spaces[2].metrics.nexits.average
old: 1.0
new: null
path: .spaces[0].spaces[2].metrics.nexits.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[2].metrics.mi.mi_visual_studio
old: 66.57259677627995
new: null
path: .spaces[0].spaces[2].metrics.mi.mi_original
old: 113.83914048743873
new: null
path: .spaces[0].spaces[2].metrics.mi.mi_sei
old: 88.63613130768158
new: null
path: .spaces[0].spaces[2].metrics.nargs.sum
old: 2.0
new: 0.0
path: .spaces[0].spaces[2].metrics.nargs.average
old: 2.0
new: null
Code
class nsWrapperCache;
Minimal test - lines (56, 56)
path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 1.0
new: null
path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 96.78778619486108
new: null
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 69.87686379496193
new: null
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 119.4894370893849
new: null
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 10.0
new: 1.0
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.027406162220640837
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 127.43782540330756
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 9.0
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 13.0
new: 1.0
path: .spaces[0].spaces[0].metrics.halstead.time
old: 41.41729325607495
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.17094017094017094
new: null
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.058286865395148
new: null
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 19.0
new: 1.0
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 61.74860596185444
new: null
path: .spaces[0].spaces[0].metrics.halstead.length
old: 30.0
new: 1.0
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 5.85
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 17.0
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 745.5112786093491
new: 0.0
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 5.0
new: 1.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 5.0
new: 1.0
path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
Code
class nsCycleCollectionTraversalCallback;
Minimal test - lines (60, 65)
path: .spaces[0].spaces[3].metrics.loc.blank
old: 1.0
new: 0.0
path: .spaces[0].spaces[3].metrics.loc.sloc
old: 7.0
new: 6.0
path: .spaces[0].spaces[3].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[3].metrics.mi.mi_sei
old: 85.5876177277901
new: 100.53618767522336
path: .spaces[0].spaces[3].metrics.mi.mi_original
old: 111.72607189463828
new: 121.94647871016232
path: .spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 65.33688414891127
new: 71.313730239861
path: .spaces[0].spaces[3].metrics.halstead.length
old: 46.0
new: 13.0
path: .spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 1.4443165629945054
new: 1.5084338826489854
path: .spaces[0].spaces[3].metrics.halstead.level
old: 0.09523809523809525
new: 0.4166666666666667
path: .spaces[0].spaces[3].metrics.halstead.bugs
old: 0.054445483288631406
new: 0.0071287677522191
path: .spaces[0].spaces[3].metrics.halstead.n2
old: 10.0
new: 5.0
path: .spaces[0].spaces[3].metrics.halstead.n1
old: 10.0
new: 4.0
path: .spaces[0].spaces[3].metrics.halstead.N2
old: 21.0
new: 6.0
path: .spaces[0].spaces[3].metrics.halstead.effort
old: 2087.491269830596
new: 98.90166004500011
path: .spaces[0].spaces[3].metrics.halstead.volume
old: 198.80869236481868
new: 41.209025018750054
path: .spaces[0].spaces[3].metrics.halstead.N1
old: 25.0
new: 7.0
path: .spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 66.43856189774725
new: 19.60964047443681
path: .spaces[0].spaces[3].metrics.halstead.vocabulary
old: 20.0
new: 9.0
path: .spaces[0].spaces[3].metrics.halstead.time
old: 115.9717372128109
new: 5.494536669166674
path: .spaces[0].spaces[3].metrics.halstead.difficulty
old: 10.5
new: 2.4
path: .spaces[0].spaces[3].metrics.nargs.sum
old: 2.0
new: 0.0
path: .spaces[0].spaces[3].metrics.nargs.average
old: 2.0
new: 0.0
path: .spaces[0].spaces[3].metrics.cyclomatic.sum
old: 1.0
new: 3.0
path: .spaces[0].spaces[3].metrics.nexits.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[3].metrics.nexits.average
old: 1.0
new: 0.0
Code
namespace JS {
template
class Heap;
template
class TenuredHeap;
} /* namespace JS */
Minimal test - lines (57, 57)
path: .spaces[0].spaces[1].metrics.halstead.n1
old: 10.0
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 2.0132897544771895
new: null
path: .spaces[0].spaces[1].metrics.halstead.difficulty
old: 7.0
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.length
old: 33.0
new: 1.0
path: .spaces[0].spaces[1].metrics.halstead.N2
old: 14.0
new: 1.0
path: .spaces[0].spaces[1].metrics.halstead.level
old: 0.14285714285714285
new: null
path: .spaces[0].spaces[1].metrics.halstead.vocabulary
old: 20.0
new: 1.0
path: .spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 66.43856189774725
new: null
path: .spaces[0].spaces[1].metrics.halstead.N1
old: 19.0
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.effort
old: 998.3653899189808
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.n2
old: 10.0
new: 1.0
path: .spaces[0].spaces[1].metrics.halstead.time
old: 55.46474388438782
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.volume
old: 142.62362713128297
new: 0.0
path: .spaces[0].spaces[1].metrics.halstead.bugs
old: 0.033296998761558366
new: 0.0
path: .spaces[0].spaces[1].metrics.loc.ploc
old: 5.0
new: 1.0
path: .spaces[0].spaces[1].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[1].metrics.loc.sloc
old: 5.0
new: 1.0
path: .spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 69.53451349123948
new: null
path: .spaces[0].spaces[1].metrics.mi.mi_original
old: 118.9040180700195
new: null
path: .spaces[0].spaces[1].metrics.mi.mi_sei
old: 95.94320507878057
new: null
path: .spaces[0].spaces[1].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].spaces[1].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].spaces[1].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].spaces[1].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[1].metrics.nargs.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[1].metrics.nargs.average
old: 1.0
new: null
Code
class nsISupports;
Minimal test - lines (48, 254)
path: .spaces[0].metrics.halstead.difficulty
old: 16.88372093023256
new: 35.397260273972606
path: .spaces[0].metrics.halstead.effort
old: 28177.535225709227
new: 170647.08692876066
path: .spaces[0].metrics.halstead.n1
old: 11.0
new: 19.0
path: .spaces[0].metrics.halstead.time
old: 1565.4186236505127
new: 9480.39371826448
path: .spaces[0].metrics.halstead.vocabulary
old: 54.0
new: 92.0
path: .spaces[0].metrics.halstead.level
old: 0.05922865013774104
new: 0.02825077399380805
path: .spaces[0].metrics.halstead.volume
old: 1668.9173756274058
new: 4820.912285526133
path: .spaces[0].metrics.halstead.estimated_program_length
old: 271.3831322572005
new: 532.5678155536693
path: .spaces[0].metrics.halstead.N1
old: 158.0
new: 467.0
path: .spaces[0].metrics.halstead.length
old: 290.0
new: 739.0
path: .spaces[0].metrics.halstead.N2
old: 132.0
new: 272.0
path: .spaces[0].metrics.halstead.bugs
old: 0.3086602802717067
new: 1.0255212516392678
path: .spaces[0].metrics.halstead.purity_ratio
old: 0.935803904335174
new: 0.7206601022377123
path: .spaces[0].metrics.halstead.n2
old: 43.0
new: 73.0
path: .spaces[0].metrics.nom.functions
old: 7.0
new: 14.0
path: .spaces[0].metrics.nom.total
old: 7.0
new: 14.0
path: .spaces[0].metrics.loc.cloc
old: 4.0
new: 70.0
path: .spaces[0].metrics.loc.ploc
old: 47.0
new: 115.0
path: .spaces[0].metrics.loc.sloc
old: 57.0
new: 207.0
path: .spaces[0].metrics.loc.blank
old: 6.0
new: 22.0
path: .spaces[0].metrics.loc.lloc
old: 23.0
new: 26.0
path: .spaces[0].metrics.mi.mi_original
old: 65.07893129205475
new: 34.300219557146676
path: .spaces[0].metrics.mi.mi_sei
old: 38.95116853862184
new: 15.726884480538295
path: .spaces[0].metrics.mi.mi_visual_studio
old: 38.05785455675717
new: 20.05860792815595
path: .spaces[0].metrics.nexits.sum
old: 5.0
new: 10.0
path: .spaces[0].metrics.cyclomatic.sum
old: 8.0
new: 27.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.173913043478261
path: .spaces[0].metrics.nargs.sum
old: 16.0
new: 13.0
path: .spaces[0].metrics.nargs.average
old: 2.2857142857142856
new: 0.9285714285714286
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 1.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 0.07142857142857142
Code
class nsCycleCollectionISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports,
NS_CYCLECOLLECTIONISUPPORTS_IID)
class nsCycleCollectionTraversalCallback;
class nsISupports;
class nsWrapperCache;
namespace JS {
template
class Heap;
template
class TenuredHeap;
} /* namespace JS */
/*
* A struct defining pure virtual methods which are called when tracing cycle
* collection paticipants. The appropriate method is called depending on the
* type of JS GC thing.
*/
struct TraceCallbacks {
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(nsWrapperCache* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
};
/*
* An implementation of TraceCallbacks that calls a single function for all JS
* GC thing types encountered. Implemented in
* nsCycleCollectorTraceJSHelpers.cpp.
*/
struct TraceCallbackFunc : public TraceCallbacks {
typedef void (*Func)(JS::GCCellPtr aPtr, const char* aName, void* aClosure);
explicit TraceCallbackFunc(Func aCb) : mCallback(aCb) {}
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(nsWrapperCache* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const override;
private:
Func mCallback;
};
/**
* Participant implementation classes
*/
class NS_NO_VTABLE nsCycleCollectionParticipant {
public:
using Flags = uint8_t;
static constexpr Flags FlagMightSkip = 1u << 0;
static constexpr Flags FlagTraverseShouldTrace = 1u << 1;
static constexpr Flags FlagMultiZoneJSHolder = 1u << 2;
static constexpr Flags AllFlags =
FlagMightSkip | FlagTraverseShouldTrace | FlagMultiZoneJSHolder;
constexpr explicit nsCycleCollectionParticipant(Flags aFlags)
: mFlags(aFlags) {
MOZ_ASSERT((aFlags & ~AllFlags) == 0);
}
NS_IMETHOD TraverseNative(void* aPtr,
nsCycleCollectionTraversalCallback& aCb) = 0;
nsresult TraverseNativeAndJS(void* aPtr,
nsCycleCollectionTraversalCallback& aCb) {
nsresult rv = TraverseNative(aPtr, aCb);
if (TraverseShouldTrace()) {
// Note, we always call Trace, even if Traverse returned
// NS_SUCCESS_INTERRUPTED_TRAVERSE.
TraceCallbackFunc noteJsChild(&nsCycleCollectionParticipant::NoteJSChild);
Trace(aPtr, noteJsChild, &aCb);
}
return rv;
}
// Implemented in nsCycleCollectorTraceJSHelpers.cpp.
static void NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
void* aClosure);
NS_IMETHOD_(void) Root(void* aPtr) = 0;
NS_IMETHOD_(void) Unlink(void* aPtr) = 0;
NS_IMETHOD_(void) Unroot(void* aPtr) = 0;
NS_IMETHOD_(const char*) ClassName() = 0;
NS_IMETHOD_(void)
Trace(void* aPtr, const TraceCallbacks& aCb, void* aClosure) {}
// CanSkip is called during nsCycleCollector_forgetSkippable. If it returns
// true, aPtr is removed from the purple buffer and therefore might be left
// out from the cycle collector graph the next time that's constructed (unless
// it's reachable in some other way).
//
// CanSkip is allowed to expand the set of certainly-alive objects by removing
// other objects from the purple buffer, marking JS things black (in the GC
// sense), and so forth. Furthermore, if aRemovingAllowed is true, this call
// is allowed to remove aPtr itself from the purple buffer.
//
// Things can return true from CanSkip if either they know they have no
// outgoing edges at all in the cycle collection graph (because then they
// can't be parts of a cycle) or they know for sure they're alive.
bool CanSkip(void* aPtr, bool aRemovingAllowed) {
return MightSkip() ? CanSkipReal(aPtr, aRemovingAllowed) : false;
}
// CanSkipInCC is called during construction of the initial set of roots for
// the cycle collector graph. If it returns true, aPtr is left out of that
// set of roots. Note that the set of roots includes whatever is in the
// purple buffer (after earlier CanSkip calls) plus various other sources of
// roots, so an object can end up having CanSkipInCC called on it even if it
// returned true from CanSkip. One example of this would be an object that
// can potentially trace JS things.
//
// CanSkipInCC is allowed to remove other objects from the purple buffer but
// should not remove aPtr and should not mark JS things black. It should also
// not modify any reference counts.
//
// Things can return true from CanSkipInCC if either they know they have no
// outgoing edges at all in the cycle collection graph or they know for sure
// they're alive _and_ none of their outgoing edges are to gray (in the GC
// sense) gcthings. See also nsWrapperCache::HasNothingToTrace and
// nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing. The restriction
// on not having outgoing edges to gray gcthings is because if we _do_ have
// them that means we have a "strong" edge to a JS thing and since we're alive
// we need to trace through it and mark keep them alive. Outgoing edges to
// C++ things don't matter here, because the criteria for when a CC
// participant is considered alive are slightly different for JS and C++
// things: JS things are only considered alive when reachable via an edge from
// a live thing, while C++ things are also considered alive when their
// refcount exceeds the number of edges via which they are reachable.
bool CanSkipInCC(void* aPtr) {
return MightSkip() ? CanSkipInCCReal(aPtr) : false;
}
// CanSkipThis is called during construction of the cycle collector graph,
// when we traverse an edge to aPtr and consider adding it to the graph. If
// it returns true, aPtr is not added to the graph.
//
// CanSkipThis is not allowed to change the liveness or reference count of any
// objects.
//
// Things can return true from CanSkipThis if either they know they have no
// outgoing edges at all in the cycle collection graph or they know for sure
// they're alive.
//
// Note that CanSkipThis doesn't have to worry about outgoing edges to gray GC
// things, because if this object could have those it already got added to the
// graph during root set construction. An object should never have
// CanSkipThis called on it if it has outgoing strong references to JS things.
bool CanSkipThis(void* aPtr) {
return MightSkip() ? CanSkipThisReal(aPtr) : false;
}
NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) = 0;
bool IsMultiZoneJSHolder() const { return mFlags & FlagMultiZoneJSHolder; }
protected:
NS_IMETHOD_(bool) CanSkipReal(void* aPtr, bool aRemovingAllowed) {
NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
return false;
}
NS_IMETHOD_(bool) CanSkipInCCReal(void* aPtr) {
NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
return false;
}
NS_IMETHOD_(bool) CanSkipThisReal(void* aPtr) {
NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
return false;
}
private:
bool MightSkip() const { return mFlags & FlagMightSkip; }
bool TraverseShouldTrace() const { return mFlags & FlagTraverseShouldTrace; }
const Flags mFlags;
};
Minimal test - lines (125, 239)
path: .spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 61.44637168252373
new: 30.596718596661898
path: .spaces[0].spaces[6].metrics.mi.mi_original
old: 105.0732955771156
new: 52.32038880029184
path: .spaces[0].spaces[6].metrics.mi.mi_sei
old: 99.51648244530158
new: 45.228071221615984
path: .spaces[0].spaces[6].metrics.loc.ploc
old: 10.0
new: 47.0
path: .spaces[0].spaces[6].metrics.loc.blank
old: 0.0
new: 12.0
path: .spaces[0].spaces[6].metrics.loc.lloc
old: 4.0
new: 20.0
path: .spaces[0].spaces[6].metrics.loc.sloc
old: 10.0
new: 115.0
path: .spaces[0].spaces[6].metrics.loc.cloc
old: 1.0
new: 56.0
path: .spaces[0].spaces[6].metrics.nexits.sum
old: 1.0
new: 6.0
path: .spaces[0].spaces[6].metrics.nexits.average
old: 1.0
new: 0.75
path: .spaces[0].spaces[6].metrics.halstead.difficulty
old: 9.23076923076923
new: 19.333333333333332
path: .spaces[0].spaces[6].metrics.halstead.n1
old: 10.0
new: 17.0
path: .spaces[0].spaces[6].metrics.halstead.bugs
old: 0.055893323238229015
new: 0.34830687849628833
path: .spaces[0].spaces[6].metrics.halstead.vocabulary
old: 23.0
new: 68.0
path: .spaces[0].spaces[6].metrics.halstead.n2
old: 13.0
new: 51.0
path: .spaces[0].spaces[6].metrics.halstead.volume
old: 235.22522171496468
new: 1747.1018354388473
path: .spaces[0].spaces[6].metrics.halstead.effort
old: 2171.309738907366
new: 33777.30215181771
path: .spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 1.5639422554751503
new: 1.2501064834209128
path: .spaces[0].spaces[6].metrics.halstead.length
old: 52.0
new: 287.0
path: .spaces[0].spaces[6].metrics.halstead.level
old: 0.10833333333333334
new: 0.05172413793103449
path: .spaces[0].spaces[6].metrics.halstead.time
old: 120.628318828187
new: 1876.5167862120952
path: .spaces[0].spaces[6].metrics.halstead.N1
old: 28.0
new: 171.0
path: .spaces[0].spaces[6].metrics.halstead.N2
old: 24.0
new: 116.0
path: .spaces[0].spaces[6].metrics.halstead.estimated_program_length
old: 81.32499728470782
new: 358.780560741802
path: .spaces[0].spaces[6].metrics.nargs.average
old: 4.0
new: 1.25
path: .spaces[0].spaces[6].metrics.nargs.sum
old: 4.0
new: 10.0
path: .spaces[0].spaces[6].metrics.cyclomatic.sum
old: 1.0
new: 13.0
path: .spaces[0].spaces[6].metrics.cyclomatic.average
old: 1.0
new: 1.4444444444444444
path: .spaces[0].spaces[6].metrics.nom.total
old: 1.0
new: 8.0
path: .spaces[0].spaces[6].metrics.nom.functions
old: 1.0
new: 8.0
path: .spaces[0].spaces[6].metrics.cognitive.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[6].metrics.cognitive.average
old: 0.0
new: 0.125
Code
class NS_NO_VTABLE nsCycleCollectionParticipant {
public:
using Flags = uint8_t;
static constexpr Flags FlagMightSkip = 1u << 0;
static constexpr Flags FlagTraverseShouldTrace = 1u << 1;
static constexpr Flags FlagMultiZoneJSHolder = 1u << 2;
static constexpr Flags AllFlags =
FlagMightSkip | FlagTraverseShouldTrace | FlagMultiZoneJSHolder;
constexpr explicit nsCycleCollectionParticipant(Flags aFlags)
: mFlags(aFlags) {
MOZ_ASSERT((aFlags & ~AllFlags) == 0);
}
NS_IMETHOD TraverseNative(void* aPtr,
nsCycleCollectionTraversalCallback& aCb) = 0;
nsresult TraverseNativeAndJS(void* aPtr,
nsCycleCollectionTraversalCallback& aCb) {
nsresult rv = TraverseNative(aPtr, aCb);
if (TraverseShouldTrace()) {
// Note, we always call Trace, even if Traverse returned
// NS_SUCCESS_INTERRUPTED_TRAVERSE.
TraceCallbackFunc noteJsChild(&nsCycleCollectionParticipant::NoteJSChild);
Trace(aPtr, noteJsChild, &aCb);
}
return rv;
}
// Implemented in nsCycleCollectorTraceJSHelpers.cpp.
static void NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
void* aClosure);
NS_IMETHOD_(void) Root(void* aPtr) = 0;
NS_IMETHOD_(void) Unlink(void* aPtr) = 0;
NS_IMETHOD_(void) Unroot(void* aPtr) = 0;
NS_IMETHOD_(const char*) ClassName() = 0;
NS_IMETHOD_(void)
Trace(void* aPtr, const TraceCallbacks& aCb, void* aClosure) {}
// CanSkip is called during nsCycleCollector_forgetSkippable. If it returns
// true, aPtr is removed from the purple buffer and therefore might be left
// out from the cycle collector graph the next time that's constructed (unless
// it's reachable in some other way).
//
// CanSkip is allowed to expand the set of certainly-alive objects by removing
// other objects from the purple buffer, marking JS things black (in the GC
// sense), and so forth. Furthermore, if aRemovingAllowed is true, this call
// is allowed to remove aPtr itself from the purple buffer.
//
// Things can return true from CanSkip if either they know they have no
// outgoing edges at all in the cycle collection graph (because then they
// can't be parts of a cycle) or they know for sure they're alive.
bool CanSkip(void* aPtr, bool aRemovingAllowed) {
return MightSkip() ? CanSkipReal(aPtr, aRemovingAllowed) : false;
}
// CanSkipInCC is called during construction of the initial set of roots for
// the cycle collector graph. If it returns true, aPtr is left out of that
// set of roots. Note that the set of roots includes whatever is in the
// purple buffer (after earlier CanSkip calls) plus various other sources of
// roots, so an object can end up having CanSkipInCC called on it even if it
// returned true from CanSkip. One example of this would be an object that
// can potentially trace JS things.
//
// CanSkipInCC is allowed to remove other objects from the purple buffer but
// should not remove aPtr and should not mark JS things black. It should also
// not modify any reference counts.
//
// Things can return true from CanSkipInCC if either they know they have no
// outgoing edges at all in the cycle collection graph or they know for sure
// they're alive _and_ none of their outgoing edges are to gray (in the GC
// sense) gcthings. See also nsWrapperCache::HasNothingToTrace and
// nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing. The restriction
// on not having outgoing edges to gray gcthings is because if we _do_ have
// them that means we have a "strong" edge to a JS thing and since we're alive
// we need to trace through it and mark keep them alive. Outgoing edges to
// C++ things don't matter here, because the criteria for when a CC
// participant is considered alive are slightly different for JS and C++
// things: JS things are only considered alive when reachable via an edge from
// a live thing, while C++ things are also considered alive when their
// refcount exceeds the number of edges via which they are reachable.
bool CanSkipInCC(void* aPtr) {
return MightSkip() ? CanSkipInCCReal(aPtr) : false;
}
// CanSkipThis is called during construction of the cycle collector graph,
// when we traverse an edge to aPtr and consider adding it to the graph. If
// it returns true, aPtr is not added to the graph.
//
// CanSkipThis is not allowed to change the liveness or reference count of any
// objects.
//
// Things can return true from CanSkipThis if either they know they have no
// outgoing edges at all in the cycle collection graph or they know for sure
// they're alive.
//
// Note that CanSkipThis doesn't have to worry about outgoing edges to gray GC
// things, because if this object could have those it already got added to the
// graph during root set construction. An object should never have
// CanSkipThis called on it if it has outgoing strong references to JS things.
bool CanSkipThis(void* aPtr) {
return MightSkip() ? CanSkipThisReal(aPtr) : false;
}
NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) = 0;
bool IsMultiZoneJSHolder() const { return mFlags & FlagMultiZoneJSHolder; }
protected:
NS_IMETHOD_(bool) CanSkipReal(void* aPtr, bool aRemovingAllowed) {
NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
return false;
}
Minimal test - lines (72, 89)
path: .spaces[0].spaces[4].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].spaces[4].metrics.nargs.average
old: 3.0
new: null
path: .spaces[0].spaces[4].metrics.nargs.sum
old: 3.0
new: 0.0
path: .spaces[0].spaces[4].metrics.mi.mi_original
old: 114.99771977101476
new: 89.19417174101484
path: .spaces[0].spaces[4].metrics.mi.mi_sei
old: 119.86396375533808
new: 53.08095711435233
path: .spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 67.25012852106127
new: 52.16033435147067
path: .spaces[0].spaces[4].metrics.halstead.N2
old: 18.0
new: 56.0
path: .spaces[0].spaces[4].metrics.halstead.length
old: 39.0
new: 172.0
path: .spaces[0].spaces[4].metrics.halstead.n2
old: 11.0
new: 15.0
path: .spaces[0].spaces[4].metrics.halstead.level
old: 0.12222222222222222
new: 0.05357142857142857
path: .spaces[0].spaces[4].metrics.halstead.effort
old: 1401.5485594503136
new: 14909.874273303383
path: .spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 71.27302875388389
new: 91.8226398830014
path: .spaces[0].spaces[4].metrics.halstead.bugs
old: 0.04174625403117913
new: 0.20192715796442023
path: .spaces[0].spaces[4].metrics.halstead.time
old: 77.86380885835075
new: 828.3263485168546
path: .spaces[0].spaces[4].metrics.halstead.volume
old: 171.30037948837168
new: 798.7432646412526
path: .spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 1.8275135577918944
new: 0.5338525574593106
path: .spaces[0].spaces[4].metrics.halstead.N1
old: 21.0
new: 116.0
path: .spaces[0].spaces[4].metrics.halstead.difficulty
old: 8.181818181818182
new: 18.666666666666668
path: .spaces[0].spaces[4].metrics.halstead.vocabulary
old: 21.0
new: 25.0
path: .spaces[0].spaces[4].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].spaces[4].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[4].metrics.nexits.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[4].metrics.nexits.average
old: 1.0
new: null
path: .spaces[0].spaces[4].metrics.loc.cloc
old: 1.0
new: 0.0
path: .spaces[0].spaces[4].metrics.loc.sloc
old: 6.0
new: 18.0
path: .spaces[0].spaces[4].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[4].metrics.loc.ploc
old: 6.0
new: 18.0
Code
struct TraceCallbacks {
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(nsWrapperCache* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
virtual void Trace(JS::Heap* aPtr, const char* aName,
void* aClosure) const = 0;
};