Bug 1591338 - Add a JS API to call a object's finalizer r=mccr8

This replaces a direct call of an object's finalizer with a more formal API. This adds some assertions and passes a valid FreeOp pointer to the finalizer rather than null.

Differential Revision: https://phabricator.services.mozilla.com/D50571

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jon Coppeard 2019-10-25 15:33:52 +00:00
parent f9b25eadca
commit e9bd719e91
3 changed files with 28 additions and 2 deletions

View File

@ -1108,6 +1108,17 @@ namespace gc {
*/
extern JS_PUBLIC_API JSObject* NewMemoryInfoObject(JSContext* cx);
/*
* Run the finalizer of a nursery-allocated JSObject that is known to be dead.
*
* This is a dangerous operation - only use this if you know what you're doing!
*
* This is used by the browser to implement nursery-allocated wrapper cached
* wrappers.
*/
extern JS_PUBLIC_API void FinalizeDeadNurseryObject(JSContext* cx,
JSObject* obj);
} /* namespace gc */
} /* namespace js */

View File

@ -8842,3 +8842,18 @@ bool js::gc::ClearEdgesTracer::onChild(const JS::GCCellPtr& thing) {
MOZ_CRASH();
return true;
}
JS_PUBLIC_API void js::gc::FinalizeDeadNurseryObject(JSContext* cx,
JSObject* obj) {
CHECK_THREAD(cx);
MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting());
MOZ_ASSERT(obj);
MOZ_ASSERT(IsInsideNursery(obj));
mozilla::DebugOnly<JSObject*> prior(obj);
MOZ_ASSERT(IsAboutToBeFinalizedUnbarriered(&prior));
MOZ_ASSERT(obj == prior);
const JSClass* jsClass = js::GetObjectClass(obj);
jsClass->doFinalize(cx->defaultFreeOp(), obj);
}

View File

@ -1158,14 +1158,14 @@ void CycleCollectedJSRuntime::GarbageCollect(JS::GCReason aReason) const {
}
void CycleCollectedJSRuntime::JSObjectsTenured() {
JSContext* cx = CycleCollectedJSContext::Get()->Context();
for (auto iter = mNurseryObjects.Iter(); !iter.Done(); iter.Next()) {
nsWrapperCache* cache = iter.Get();
JSObject* wrapper = cache->GetWrapperMaybeDead();
MOZ_DIAGNOSTIC_ASSERT(wrapper || recordreplay::IsReplaying());
if (!JS::ObjectIsTenured(wrapper)) {
MOZ_ASSERT(!cache->PreservingWrapper());
const JSClass* jsClass = js::GetObjectClass(wrapper);
jsClass->doFinalize(nullptr, wrapper);
js::gc::FinalizeDeadNurseryObject(cx, wrapper);
}
}