Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-04-30 21:26:08 +08:00
commit beb68187e5
98 changed files with 13981 additions and 982 deletions

View file

@ -72,6 +72,7 @@
#include "mozilla/dom/ScriptSettings.h"
#include "jsprf.h"
#include "js/Debug.h"
#include "jsfriendapi.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionNoteRootCallback.h"
#include "nsCycleCollectionParticipant.h"
@ -642,25 +643,33 @@ CycleCollectedJSContext::NoteGCThingXPCOMChildren(const js::Class* aClasp,
}
// XXX This test does seem fragile, we should probably whitelist classes
// that do hold a strong reference, but that might not be possible.
else if (aClasp->flags & JSCLASS_HAS_PRIVATE &&
aClasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
if (aClasp->flags & JSCLASS_HAS_PRIVATE &&
aClasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "js::GetObjectPrivate(obj)");
aCb.NoteXPCOMChild(static_cast<nsISupports*>(js::GetObjectPrivate(aObj)));
} else {
const DOMJSClass* domClass = GetDOMClass(aObj);
if (domClass) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "UnwrapDOMObject(obj)");
// It's possible that our object is an unforgeable holder object, in
// which case it doesn't actually have a C++ DOM object associated with
// it. Use UnwrapPossiblyNotInitializedDOMObject, which produces null in
// that case, since NoteXPCOMChild/NoteNativeChild are null-safe.
if (domClass->mDOMObjectIsISupports) {
aCb.NoteXPCOMChild(UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObj));
} else if (domClass->mParticipant) {
aCb.NoteNativeChild(UnwrapPossiblyNotInitializedDOMObject<void>(aObj),
domClass->mParticipant);
}
}
return;
}
const DOMJSClass* domClass = GetDOMClass(aObj);
if (domClass) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "UnwrapDOMObject(obj)");
// It's possible that our object is an unforgeable holder object, in
// which case it doesn't actually have a C++ DOM object associated with
// it. Use UnwrapPossiblyNotInitializedDOMObject, which produces null in
// that case, since NoteXPCOMChild/NoteNativeChild are null-safe.
if (domClass->mDOMObjectIsISupports) {
aCb.NoteXPCOMChild(
UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObj));
} else if (domClass->mParticipant) {
aCb.NoteNativeChild(UnwrapPossiblyNotInitializedDOMObject<void>(aObj),
domClass->mParticipant);
}
return;
}
JS::Value value = js::MaybeGetScriptPrivate(aObj);
if (!value.isUndefined()) {
aCb.NoteXPCOMChild(static_cast<nsISupports*>(value.toPrivate()));
}
}

View file

@ -568,6 +568,13 @@
ERROR(NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC, FAILURE(1027)),
ERROR(NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC, FAILURE(1028)),
/* When manipulating the bytecode cache with the JS API, some transcoding
* errors, such as a different bytecode format can cause failures of the
* decoding process.
*/
ERROR(NS_ERROR_DOM_JS_DECODING_ERROR, FAILURE(1030)),
/* May be used to indicate when e.g. setting a property value didn't
* actually change the value, like for obj.foo = "bar"; obj.foo = "bar";
* the second assignment throws NS_SUCCESS_DOM_NO_OPERATION.

View file

@ -337,7 +337,7 @@ public:
// Base types
////////////////////////////////////////////////////////////////////////
struct PtrInfo;
class PtrInfo;
class EdgePool
{
@ -533,13 +533,15 @@ enum NodeColor { black, white, grey };
// hundreds of thousands of them to be allocated and touched
// repeatedly during each cycle collection.
struct PtrInfo
class PtrInfo final
{
public:
void* mPointer;
nsCycleCollectionParticipant* mParticipant;
uint32_t mColor : 2;
uint32_t mInternalRefs : 30;
uint32_t mRefCount;
private:
EdgePool::Iterator mFirstChild;
@ -609,8 +611,29 @@ public:
CC_GRAPH_ASSERT(aLastChild.Initialized());
(this + 1)->mFirstChild = aLastChild;
}
void AnnotatedReleaseAssert(bool aCondition, const char* aMessage);
};
void
PtrInfo::AnnotatedReleaseAssert(bool aCondition, const char* aMessage)
{
if (aCondition) {
return;
}
#ifdef MOZ_CRASHREPORTER
const char* piName = "Unknown";
if (mParticipant) {
piName = mParticipant->ClassName();
}
nsPrintfCString msg("%s, for class %s", aMessage, piName);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CycleCollector"), msg);
#endif
MOZ_CRASH();
}
/**
* A structure designed to be used like a linked list of PtrInfo, except
* it allocates many PtrInfos at a time.
@ -2297,8 +2320,10 @@ CCGraphBuilder::NoteNativeRoot(void* aRoot,
NS_IMETHODIMP_(void)
CCGraphBuilder::DescribeRefCountedNode(nsrefcnt aRefCount, const char* aObjName)
{
MOZ_RELEASE_ASSERT(aRefCount != 0, "CCed refcounted object has zero refcount");
MOZ_RELEASE_ASSERT(aRefCount != UINT32_MAX, "CCed refcounted object has overflowing refcount");
mCurrPi->AnnotatedReleaseAssert(aRefCount != 0,
"CCed refcounted object has zero refcount");
mCurrPi->AnnotatedReleaseAssert(aRefCount != UINT32_MAX,
"CCed refcounted object has overflowing refcount");
mResults.mVisitedRefCounted++;
@ -3112,9 +3137,8 @@ nsCycleCollector::ScanWhiteNodes(bool aFullySynchGraphBuild)
continue;
}
if (pi->mInternalRefs > pi->mRefCount) {
MOZ_CRASH();
}
pi->AnnotatedReleaseAssert(pi->mInternalRefs <= pi->mRefCount,
"More references to an object than its refcount");
// This node will get marked black in the next pass.
}

View file

@ -322,6 +322,20 @@ protected:
*/
virtual void NotifyExpiredLocked(T*, const AutoLock&) = 0;
/**
* This may be overridden to perform any post-aging work that needs to be
* done while still holding the lock. It will be called once after each timer
* event, and each low memory event has been handled.
*/
virtual void NotifyHandlerEndLocked(const AutoLock&) { };
/**
* This may be overridden to perform any post-aging work that needs to be
* done outside the lock. It will be called once after each
* NotifyEndTransactionLocked call.
*/
virtual void NotifyHandlerEnd() { };
virtual Mutex& GetMutex() = 0;
private:
@ -364,18 +378,26 @@ private:
};
void HandleLowMemory() {
AutoLock lock(GetMutex());
AgeAllGenerationsLocked(lock);
{
AutoLock lock(GetMutex());
AgeAllGenerationsLocked(lock);
NotifyHandlerEndLocked(lock);
}
NotifyHandlerEnd();
}
void HandleTimeout() {
AutoLock lock(GetMutex());
AgeOneGenerationLocked(lock);
// Cancel the timer if we have no objects to track
if (IsEmptyLocked(lock)) {
mTimer->Cancel();
mTimer = nullptr;
{
AutoLock lock(GetMutex());
AgeOneGenerationLocked(lock);
// Cancel the timer if we have no objects to track
if (IsEmptyLocked(lock)) {
mTimer->Cancel();
mTimer = nullptr;
}
NotifyHandlerEndLocked(lock);
}
NotifyHandlerEnd();
}
static void TimerCallback(nsITimer* aTimer, void* aThis)
@ -449,6 +471,14 @@ class nsExpirationTracker : protected ::detail::SingleThreadedExpirationTracker<
NotifyExpired(aObject);
}
/**
* Since there are no users of these callbacks in the single threaded case,
* we mark them as final with the hope that the compiler can optimize the
* method calls out entirely.
*/
void NotifyHandlerEndLocked(const AutoLock&) final override { }
void NotifyHandlerEnd() final override { }
protected:
virtual void NotifyExpired(T* aObj) = 0;