XPConnect object wrapping: Difference between revisions

No edit summary
 
Line 45: Line 45:
# As long as a C++ caller holds a strong XPCOM reference to the <tt>XPCWrappedNative</tt>, the <tt>XPCWrappedNative</tt> has refcount >= 2. It turns out that every live <tt>XPCWrappedNative</tt> is ''also'' held in a hashtable, internal to xpconnect. The hashtable maps <tt>nsISupports*</tt> to <tt>XPCWrappedNative*</tt>. During JS GC a function (<tt>WrappedNativeJSGCThingMarker</tt> in <tt>xpcwrappednativescope.cpp</tt>) is run over that hashtable, marking the <tt>JSObject</tt> pointed to by every <tt>XPCWrappedNative</tt> with refcount > 1. This keeps things like "preserved wrappers" alive (see further below).
# As long as a C++ caller holds a strong XPCOM reference to the <tt>XPCWrappedNative</tt>, the <tt>XPCWrappedNative</tt> has refcount >= 2. It turns out that every live <tt>XPCWrappedNative</tt> is ''also'' held in a hashtable, internal to xpconnect. The hashtable maps <tt>nsISupports*</tt> to <tt>XPCWrappedNative*</tt>. During JS GC a function (<tt>WrappedNativeJSGCThingMarker</tt> in <tt>xpcwrappednativescope.cpp</tt>) is run over that hashtable, marking the <tt>JSObject</tt> pointed to by every <tt>XPCWrappedNative</tt> with refcount > 1. This keeps things like "preserved wrappers" alive (see further below).
# Many C++ callers don't construct <tt>XPCWrappedNatives</tt> themselves, they actually call <tt>XPConnect::WrapNative()</tt>. <tt>WrapNative()</tt> constructs the <tt>XPCWrappedNative</tt> and tables it, but returns a <tt>XPCJSObjectHolder</tt> pointing to the <tt>JSObject</tt>. <tt>XPCJSObjectHolder</tt> ''does'' keep the <tt>JSObject</tt> alive for the duration of its use, by rooting. See <tt>XPCJSObjectHolder::XPCJSObjectHolder</tt> in <tt>xpcwrappednative.cpp</tt>.
# Many C++ callers don't construct <tt>XPCWrappedNatives</tt> themselves, they actually call <tt>XPConnect::WrapNative()</tt>. <tt>WrapNative()</tt> constructs the <tt>XPCWrappedNative</tt> and tables it, but returns a <tt>XPCJSObjectHolder</tt> pointing to the <tt>JSObject</tt>. <tt>XPCJSObjectHolder</tt> ''does'' keep the <tt>JSObject</tt> alive for the duration of its use, by rooting. See <tt>XPCJSObjectHolder::XPCJSObjectHolder</tt> in <tt>xpcwrappednative.cpp</tt>.
# If the C++ caller is part of xpconnect itself, and is operating on <tt>XPCWrappedNatives</tt> that aren't in the table yet, the caller may store a pointer to an <tt>XPCWrappedNative<tt> in an <tt>AutoMarkingWrappedNativePtr</tt>. This is a special type which inserts itself into a global per-thread linked list and also receives a call during JS GC, which it forwards on to the <tt>AutoMark()</tt> method on the <tt>XPCWrappedNative</tt>, which subsequently causes the <tt>JSObject</tt> to be marked (thus kept alive). It's not clear to me why this is done rather than rooting or automatically inserting into the table, but it is. There is some baroque macrology and locking / work-interleaving code that suggests the answer may be complicated. <tt>AutoMarkingWrappedNativePtr</tt> is private to the implementation of xpconnect, so you won't see it in normal XPCOM-using client code.
# If the C++ caller is part of xpconnect itself, and is operating on <tt>XPCWrappedNatives</tt> that aren't in the table yet, the caller may store a pointer to an <tt>XPCWrappedNative</tt> in an <tt>AutoMarkingWrappedNativePtr</tt>. This is a special type which inserts itself into a global per-thread linked list and also receives a call during JS GC, which it forwards on to the <tt>AutoMark()</tt> method on the <tt>XPCWrappedNative</tt>, which subsequently causes the <tt>JSObject</tt> to be marked (thus kept alive). It's not clear to me why this is done rather than rooting or automatically inserting into the table, but it is. There is some baroque macrology and locking / work-interleaving code that suggests the answer may be complicated. <tt>AutoMarkingWrappedNativePtr</tt> is private to the implementation of xpconnect, so you won't see it in normal XPCOM-using client code.
 


=== Native Wrappers ===
=== Native Wrappers ===
37

edits