mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and mozilla-inbound
This commit is contained in:
commit
6618255819
@ -161,6 +161,33 @@ nsPropertyTable::Enumerate(nsPropertyOwner aObject,
|
||||
}
|
||||
}
|
||||
|
||||
struct PropertyEnumeratorData
|
||||
{
|
||||
nsIAtom* mName;
|
||||
NSPropertyFunc mCallBack;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
PropertyEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
|
||||
PRUint32 aNumber, void* aArg)
|
||||
{
|
||||
PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(aHdr);
|
||||
PropertyEnumeratorData* data = static_cast<PropertyEnumeratorData*>(aArg);
|
||||
data->mCallBack(const_cast<void*>(entry->key), data->mName, entry->value,
|
||||
data->mData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
|
||||
{
|
||||
for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
|
||||
PropertyEnumeratorData data = { prop->mName, aCallBack, aData };
|
||||
PL_DHashTableEnumerate(&prop->mObjectValueMap, PropertyEnumerator, &data);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
|
||||
nsIAtom *aPropertyName,
|
||||
|
@ -181,6 +181,13 @@ class nsPropertyTable
|
||||
NS_HIDDEN_(void) Enumerate(nsPropertyOwner aObject,
|
||||
NSPropertyFunc aCallback, void *aData);
|
||||
|
||||
/**
|
||||
* Enumerate all the properties.
|
||||
* For every property |aCallback| will be called with arguments the owner,
|
||||
* the property name, the property value and |aData|.
|
||||
*/
|
||||
NS_HIDDEN_(void) EnumerateAll(NSPropertyFunc aCallback, void *aData);
|
||||
|
||||
/**
|
||||
* Deletes all of the properties for all objects in the property
|
||||
* table, calling the destructor function for each property.
|
||||
|
@ -867,6 +867,11 @@ public:
|
||||
|
||||
void SelectPointers(GCGraphBuilder &builder);
|
||||
|
||||
// RemoveSkippable removes entries from the purple buffer if
|
||||
// nsPurpleBufferEntry::mObject is null or if the object's
|
||||
// nsXPCOMCycleCollectionParticipant::CanSkip() returns true.
|
||||
void RemoveSkippable();
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
void NoteAll(GCGraphBuilder &builder);
|
||||
|
||||
@ -985,8 +990,22 @@ void
|
||||
nsPurpleBuffer::SelectPointers(GCGraphBuilder &aBuilder)
|
||||
{
|
||||
#ifdef DEBUG_CC
|
||||
// Can't use mCount here, since it may include null entries.
|
||||
PRUint32 realCount = 0;
|
||||
for (Block *b = &mFirstBlock; b; b = b->mNext) {
|
||||
for (nsPurpleBufferEntry *e = b->mEntries,
|
||||
*eEnd = ArrayEnd(b->mEntries);
|
||||
e != eEnd; ++e) {
|
||||
if (!(PRUword(e->mObject) & PRUword(1))) {
|
||||
if (e->mObject) {
|
||||
++realCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ABORT_IF_FALSE(mCompatObjects.Count() + mNormalObjects.Count() ==
|
||||
mCount,
|
||||
realCount,
|
||||
"count out of sync");
|
||||
#endif
|
||||
|
||||
@ -1006,16 +1025,7 @@ nsPurpleBuffer::SelectPointers(GCGraphBuilder &aBuilder)
|
||||
// This is a real entry (rather than something on the
|
||||
// free list).
|
||||
if (!e->mObject || AddPurpleRoot(aBuilder, e->mObject)) {
|
||||
#ifdef DEBUG_CC
|
||||
mNormalObjects.RemoveEntry(e->mObject);
|
||||
#endif
|
||||
--mCount;
|
||||
// Put this entry on the free list in case some
|
||||
// call to AddPurpleRoot fails and we don't rebuild
|
||||
// the free list below.
|
||||
e->mNextInFreeList = (nsPurpleBufferEntry*)
|
||||
(PRUword(mFreeList) | PRUword(1));
|
||||
mFreeList = e;
|
||||
Remove(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1085,6 +1095,9 @@ struct nsCycleCollector
|
||||
|
||||
nsPurpleBuffer mPurpleBuf;
|
||||
|
||||
CC_BeforeUnlinkCallback mBeforeUnlinkCB;
|
||||
CC_ForgetSkippableCallback mForgetSkippableCB;
|
||||
|
||||
void RegisterRuntime(PRUint32 langID,
|
||||
nsCycleCollectionLanguageRuntime *rt);
|
||||
nsCycleCollectionLanguageRuntime * GetRuntime(PRUint32 langID);
|
||||
@ -1095,6 +1108,8 @@ struct nsCycleCollector
|
||||
void ScanRoots();
|
||||
void ScanWeakMaps();
|
||||
|
||||
void ForgetSkippable();
|
||||
|
||||
// returns whether anything was collected
|
||||
bool CollectWhite(nsICycleCollectorListener *aListener);
|
||||
|
||||
@ -1139,6 +1154,8 @@ struct nsCycleCollector
|
||||
void Allocated(void *n, size_t sz);
|
||||
void Freed(void *n);
|
||||
|
||||
void LogPurpleRemoval(void* aObject);
|
||||
|
||||
void ExplainLiveExpectedGarbage();
|
||||
bool CreateReversedEdges();
|
||||
void DestroyReversedEdges();
|
||||
@ -1772,7 +1789,8 @@ GCGraphBuilder::NoteXPCOMChild(nsISupports *child)
|
||||
|
||||
nsXPCOMCycleCollectionParticipant *cp;
|
||||
ToParticipant(child, &cp);
|
||||
if (cp) {
|
||||
if (cp && !cp->CanSkipThis(child)) {
|
||||
|
||||
PtrInfo *childPi = AddNode(child, cp, nsIProgrammingLanguage::CPLUSPLUS);
|
||||
if (!childPi)
|
||||
return;
|
||||
@ -1878,7 +1896,7 @@ GCGraphBuilder::AddWeakMapNode(void *node)
|
||||
|
||||
cp = mRuntimes[nsIProgrammingLanguage::JAVASCRIPT]->ToParticipant(node);
|
||||
NS_ASSERTION(cp, "Javascript runtime participant should be non-null.");
|
||||
return AddNode(node, cp);
|
||||
return AddNode(node, cp, nsIProgrammingLanguage::JAVASCRIPT);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
@ -1905,10 +1923,12 @@ AddPurpleRoot(GCGraphBuilder &builder, nsISupports *root)
|
||||
nsXPCOMCycleCollectionParticipant *cp;
|
||||
ToParticipant(root, &cp);
|
||||
|
||||
PtrInfo *pinfo = builder.AddNode(root, cp,
|
||||
nsIProgrammingLanguage::CPLUSPLUS);
|
||||
if (!pinfo) {
|
||||
return false;
|
||||
if (!cp->CanSkipInCC(root)) {
|
||||
PtrInfo *pinfo = builder.AddNode(root, cp,
|
||||
nsIProgrammingLanguage::CPLUSPLUS);
|
||||
if (!pinfo) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cp->UnmarkPurple(root);
|
||||
@ -1916,6 +1936,32 @@ AddPurpleRoot(GCGraphBuilder &builder, nsISupports *root)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsPurpleBuffer::RemoveSkippable()
|
||||
{
|
||||
// Walk through all the blocks.
|
||||
for (Block *b = &mFirstBlock; b; b = b->mNext) {
|
||||
for (nsPurpleBufferEntry *e = b->mEntries,
|
||||
*eEnd = ArrayEnd(b->mEntries);
|
||||
e != eEnd; ++e) {
|
||||
if (!(PRUword(e->mObject) & PRUword(1))) {
|
||||
// This is a real entry (rather than something on the
|
||||
// free list).
|
||||
if (e->mObject) {
|
||||
nsISupports* o = canonicalize(e->mObject);
|
||||
nsXPCOMCycleCollectionParticipant* cp;
|
||||
ToParticipant(o, &cp);
|
||||
if (!cp->CanSkip(o)) {
|
||||
continue;
|
||||
}
|
||||
cp->UnmarkPurple(o);
|
||||
}
|
||||
Remove(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
static PLDHashOperator
|
||||
noteAllCallback(nsVoidPtrHashKey* key, void* userArg)
|
||||
@ -1949,6 +1995,19 @@ nsCycleCollector::SelectPurple(GCGraphBuilder &builder)
|
||||
mPurpleBuf.SelectPointers(builder);
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::ForgetSkippable()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nsnull, "cycle-collector-forget-skippable", nsnull);
|
||||
}
|
||||
mPurpleBuf.RemoveSkippable();
|
||||
if (mForgetSkippableCB) {
|
||||
mForgetSkippableCB();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::MarkRoots(GCGraphBuilder &builder)
|
||||
{
|
||||
@ -2130,6 +2189,9 @@ nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener)
|
||||
}
|
||||
}
|
||||
|
||||
if (mBeforeUnlinkCB) {
|
||||
mBeforeUnlinkCB();
|
||||
}
|
||||
#if defined(DEBUG_CC) && !defined(__MINGW32__) && defined(WIN32)
|
||||
struct _CrtMemState ms1, ms2;
|
||||
_CrtMemCheckpoint(&ms1);
|
||||
@ -2387,10 +2449,12 @@ nsCycleCollector::nsCycleCollector() :
|
||||
mVisitedGCed(0),
|
||||
#ifdef DEBUG_CC
|
||||
mPurpleBuf(mParams, mStats),
|
||||
mPtrLog(nsnull)
|
||||
mPtrLog(nsnull),
|
||||
#else
|
||||
mPurpleBuf(mParams)
|
||||
mPurpleBuf(mParams),
|
||||
#endif
|
||||
mBeforeUnlinkCB(nsnull),
|
||||
mForgetSkippableCB(nsnull)
|
||||
{
|
||||
#ifdef DEBUG_CC
|
||||
mExpectedGarbage.Init();
|
||||
@ -2657,6 +2721,27 @@ nsCycleCollector::Forget2(nsPurpleBufferEntry *e)
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
LogPurpleRemoval(e->mObject);
|
||||
#endif
|
||||
|
||||
mPurpleBuf.Remove(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
void
|
||||
nsCycleCollector_logPurpleRemoval(void* aObject)
|
||||
{
|
||||
if (sCollector) {
|
||||
sCollector->LogPurpleRemoval(aObject);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::LogPurpleRemoval(void* aObject)
|
||||
{
|
||||
AbortIfOffMainThreadIfCheckFast();
|
||||
|
||||
mStats.mForgetNode++;
|
||||
|
||||
#ifndef __MINGW32__
|
||||
@ -2667,15 +2752,11 @@ nsCycleCollector::Forget2(nsPurpleBufferEntry *e)
|
||||
if (mParams.mLogPointers) {
|
||||
if (!mPtrLog)
|
||||
mPtrLog = fopen("pointer_log", "w");
|
||||
fprintf(mPtrLog, "F %p\n", static_cast<void*>(e->mObject));
|
||||
fprintf(mPtrLog, "F %p\n", aObject);
|
||||
}
|
||||
#endif
|
||||
|
||||
mPurpleBuf.Remove(e);
|
||||
return true;
|
||||
mPurpleBuf.mNormalObjects.RemoveEntry(aObject);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
void
|
||||
nsCycleCollector::Allocated(void *n, size_t sz)
|
||||
{
|
||||
@ -3727,6 +3808,30 @@ nsCycleCollector_startup()
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_setBeforeUnlinkCallback(CC_BeforeUnlinkCallback aCB)
|
||||
{
|
||||
if (sCollector) {
|
||||
sCollector->mBeforeUnlinkCB = aCB;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB)
|
||||
{
|
||||
if (sCollector) {
|
||||
sCollector->mForgetSkippableCB = aCB;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_forgetSkippable()
|
||||
{
|
||||
if (sCollector) {
|
||||
sCollector->ForgetSkippable();
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsCycleCollector_collect(nsICycleCollectorListener *aListener)
|
||||
{
|
||||
|
@ -63,6 +63,19 @@ struct nsCycleCollectionLanguageRuntime
|
||||
};
|
||||
|
||||
nsresult nsCycleCollector_startup();
|
||||
|
||||
typedef void (*CC_BeforeUnlinkCallback)(void);
|
||||
void nsCycleCollector_setBeforeUnlinkCallback(CC_BeforeUnlinkCallback aCB);
|
||||
|
||||
typedef void (*CC_ForgetSkippableCallback)(void);
|
||||
void nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB);
|
||||
|
||||
void nsCycleCollector_forgetSkippable();
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
void nsCycleCollector_logPurpleRemoval(void* aObject);
|
||||
#endif
|
||||
|
||||
// Returns the number of collected nodes.
|
||||
PRUint32 nsCycleCollector_collect(nsICycleCollectorListener *aListener);
|
||||
PRUint32 nsCycleCollector_suspectedCount();
|
||||
|
@ -164,6 +164,9 @@ class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
|
||||
: public nsScriptObjectTracer
|
||||
{
|
||||
public:
|
||||
nsXPCOMCycleCollectionParticipant() : mMightSkip(false) {}
|
||||
nsXPCOMCycleCollectionParticipant(bool aSkip) : mMightSkip(aSkip) {}
|
||||
|
||||
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
|
||||
|
||||
NS_IMETHOD Root(void *p);
|
||||
@ -175,6 +178,49 @@ public:
|
||||
NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
|
||||
|
||||
bool CheckForRightISupports(nsISupports *s);
|
||||
|
||||
// If CanSkip returns true, p is removed from the purple buffer during
|
||||
// a call to nsCycleCollector_forgetSkippable().
|
||||
// Note, calling CanSkip may remove objects from the purple buffer!
|
||||
bool CanSkip(void *p)
|
||||
{
|
||||
return mMightSkip ? CanSkipReal(p) : false;
|
||||
}
|
||||
|
||||
// If CanSkipInCC returns true, p is skipped when selecting roots for the
|
||||
// cycle collector graph.
|
||||
// Note, calling CanSkipInCC may remove other objects from the purple buffer!
|
||||
bool CanSkipInCC(void *p)
|
||||
{
|
||||
return mMightSkip ? CanSkipInCCReal(p) : false;
|
||||
}
|
||||
|
||||
// If CanSkipThis returns true, p is not added to the graph.
|
||||
// This method is called during cycle collection, so don't
|
||||
// change the state of any objects!
|
||||
bool CanSkipThis(void *p)
|
||||
{
|
||||
return mMightSkip ? CanSkipThisReal(p) : false;
|
||||
}
|
||||
protected:
|
||||
NS_IMETHOD_(bool) CanSkipReal(void *p)
|
||||
{
|
||||
NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
|
||||
return false;
|
||||
}
|
||||
NS_IMETHOD_(bool) CanSkipInCCReal(void *p)
|
||||
{
|
||||
NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
|
||||
return false;
|
||||
}
|
||||
NS_IMETHOD_(bool) CanSkipThisReal(void *p)
|
||||
{
|
||||
NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mMightSkip;
|
||||
};
|
||||
|
||||
#undef IMETHOD_VISIBILITY
|
||||
@ -245,6 +291,45 @@ public:
|
||||
#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
|
||||
NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class) \
|
||||
NS_IMETHODIMP_(bool) \
|
||||
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p) \
|
||||
{ \
|
||||
nsISupports *s = static_cast<nsISupports*>(p); \
|
||||
NS_ASSERTION(CheckForRightISupports(s), \
|
||||
"not the nsISupports pointer we expect"); \
|
||||
_class *tmp = Downcast(s);
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class) \
|
||||
NS_IMETHODIMP_(bool) \
|
||||
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p) \
|
||||
{ \
|
||||
nsISupports *s = static_cast<nsISupports*>(p); \
|
||||
NS_ASSERTION(CheckForRightISupports(s), \
|
||||
"not the nsISupports pointer we expect"); \
|
||||
_class *tmp = Downcast(s);
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \
|
||||
NS_IMETHODIMP_(bool) \
|
||||
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p) \
|
||||
{ \
|
||||
nsISupports *s = static_cast<nsISupports*>(p); \
|
||||
NS_ASSERTION(CheckForRightISupports(s), \
|
||||
"not the nsISupports pointer we expect"); \
|
||||
_class *tmp = Downcast(s);
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \
|
||||
return false; \
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers for implementing nsCycleCollectionParticipant::Unlink
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -552,6 +637,24 @@ class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||
}; \
|
||||
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||
|
||||
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
|
||||
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||
: public nsXPCOMCycleCollectionParticipant \
|
||||
{ \
|
||||
public: \
|
||||
NS_CYCLE_COLLECTION_INNERCLASS () : nsXPCOMCycleCollectionParticipant(true) {} \
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
|
||||
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
|
||||
protected: \
|
||||
NS_IMETHOD_(bool) CanSkipReal(void *p); \
|
||||
NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
|
||||
NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
|
||||
}; \
|
||||
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||
|
||||
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
|
||||
|
||||
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
|
||||
|
||||
|
@ -226,6 +226,18 @@ public:
|
||||
mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
|
||||
}
|
||||
|
||||
void RemovePurple()
|
||||
{
|
||||
NS_ASSERTION(IsPurple(), "must be purple");
|
||||
#ifdef DEBUG_CC
|
||||
nsCycleCollector_logPurpleRemoval(
|
||||
NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject);
|
||||
#endif
|
||||
// The entry will be added to the free list later.
|
||||
NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject = nsnull;
|
||||
unmarkPurple();
|
||||
}
|
||||
|
||||
bool IsPurple() const
|
||||
{
|
||||
NS_ASSERTION(mTagged != NS_CCAR_TAGGED_STABILIZED_REFCNT,
|
||||
|
Loading…
Reference in New Issue
Block a user