mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 14:46:02 +00:00
Bug 882162: Part 8 - Move the rest of nsCycleCollectionJSRuntime's implementation into mozilla::CycleCollectedJSRuntime. r=mccr8
This commit is contained in:
parent
213c4bdde8
commit
9ad3187e9b
@ -248,55 +248,7 @@ nsXPConnect::NeedCollect()
|
|||||||
void
|
void
|
||||||
nsXPConnect::Collect(uint32_t reason)
|
nsXPConnect::Collect(uint32_t reason)
|
||||||
{
|
{
|
||||||
// We're dividing JS objects into 2 categories:
|
return GetRuntime()->Collect(reason);
|
||||||
//
|
|
||||||
// 1. "real" roots, held by the JS engine itself or rooted through the root
|
|
||||||
// and lock JS APIs. Roots from this category are considered black in the
|
|
||||||
// cycle collector, any cycle they participate in is uncollectable.
|
|
||||||
//
|
|
||||||
// 2. roots held by C++ objects that participate in cycle collection,
|
|
||||||
// held by XPConnect (see XPCJSRuntime::TraceXPConnectRoots). Roots from
|
|
||||||
// this category are considered grey in the cycle collector, their final
|
|
||||||
// color depends on the objects that hold them.
|
|
||||||
//
|
|
||||||
// Note that if a root is in both categories it is the fact that it is in
|
|
||||||
// category 1 that takes precedence, so it will be considered black.
|
|
||||||
//
|
|
||||||
// During garbage collection we switch to an additional mark color (gray)
|
|
||||||
// when tracing inside TraceXPConnectRoots. This allows us to walk those
|
|
||||||
// roots later on and add all objects reachable only from them to the
|
|
||||||
// cycle collector.
|
|
||||||
//
|
|
||||||
// Phases:
|
|
||||||
//
|
|
||||||
// 1. marking of the roots in category 1 by having the JS GC do its marking
|
|
||||||
// 2. marking of the roots in category 2 by XPCJSRuntime::TraceXPConnectRoots
|
|
||||||
// using an additional color (gray).
|
|
||||||
// 3. end of GC, GC can sweep its heap
|
|
||||||
//
|
|
||||||
// At some later point, when the cycle collector runs:
|
|
||||||
//
|
|
||||||
// 4. walk gray objects and add them to the cycle collector, cycle collect
|
|
||||||
//
|
|
||||||
// JS objects that are part of cycles the cycle collector breaks will be
|
|
||||||
// collected by the next JS.
|
|
||||||
//
|
|
||||||
// If WantAllTraces() is false the cycle collector will not traverse roots
|
|
||||||
// from category 1 or any JS objects held by them. Any JS objects they hold
|
|
||||||
// will already be marked by the JS GC and will thus be colored black
|
|
||||||
// themselves. Any C++ objects they hold will have a missing (untraversed)
|
|
||||||
// edge from the JS object to the C++ object and so it will be marked black
|
|
||||||
// too. This decreases the number of objects that the cycle collector has to
|
|
||||||
// deal with.
|
|
||||||
// To improve debugging, if WantAllTraces() is true all JS objects are
|
|
||||||
// traversed.
|
|
||||||
|
|
||||||
MOZ_ASSERT(reason < JS::gcreason::NUM_REASONS);
|
|
||||||
JS::gcreason::Reason gcreason = (JS::gcreason::Reason)reason;
|
|
||||||
|
|
||||||
JSRuntime *rt = GetRuntime()->Runtime();
|
|
||||||
JS::PrepareForFullGC(rt);
|
|
||||||
JS::GCForReason(rt, gcreason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -342,34 +294,10 @@ nsXPConnect::NotifyEnterMainThread()
|
|||||||
mRuntime->NotifyEnterMainThread();
|
mRuntime->NotifyEnterMainThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return true if there exists a JSContext with a default global whose current
|
|
||||||
* inner is gray. The intent is to look for JS Object windows. We don't merge
|
|
||||||
* system compartments, so we don't use them to trigger merging CCs.
|
|
||||||
*/
|
|
||||||
bool
|
bool
|
||||||
nsXPConnect::UsefulToMergeZones()
|
nsXPConnect::UsefulToMergeZones()
|
||||||
{
|
{
|
||||||
JSContext *iter = nullptr;
|
return GetRuntime()->UsefulToMergeZones();
|
||||||
JSContext *cx;
|
|
||||||
while ((cx = JS_ContextIterator(GetRuntime()->Runtime(), &iter))) {
|
|
||||||
// Skip anything without an nsIScriptContext, as well as any scx whose
|
|
||||||
// NativeGlobal() is not an outer window (this happens with XUL Prototype
|
|
||||||
// compilation scopes, for example, which we're not interested in).
|
|
||||||
nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
|
|
||||||
JS::RootedObject global(cx, scx ? scx->GetNativeGlobal() : nullptr);
|
|
||||||
if (!global || !js::GetObjectParent(global)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Grab the inner from the outer.
|
|
||||||
global = JS_ObjectToInnerObject(cx, global);
|
|
||||||
MOZ_ASSERT(!js::GetObjectParent(global));
|
|
||||||
if (JS::GCThingIsMarkedGray(global) &&
|
|
||||||
!js::IsSystemCompartment(js::GetObjectCompartment(global))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCycleCollectionParticipant *
|
nsCycleCollectionParticipant *
|
||||||
|
@ -507,10 +507,10 @@ public:
|
|||||||
virtual void NotifyEnterMainThread(); // DONE
|
virtual void NotifyEnterMainThread(); // DONE
|
||||||
virtual nsresult BeginCycleCollection(nsCycleCollectionNoteRootCallback &cb); // DONE
|
virtual nsresult BeginCycleCollection(nsCycleCollectionNoteRootCallback &cb); // DONE
|
||||||
virtual nsCycleCollectionParticipant *GetParticipant(); // DONE
|
virtual nsCycleCollectionParticipant *GetParticipant(); // DONE
|
||||||
virtual bool UsefulToMergeZones();
|
virtual bool UsefulToMergeZones(); // DONE
|
||||||
virtual void FixWeakMappingGrayBits(); // DONE
|
virtual void FixWeakMappingGrayBits(); // DONE
|
||||||
virtual bool NeedCollect(); // DONE
|
virtual bool NeedCollect(); // DONE
|
||||||
virtual void Collect(uint32_t reason);
|
virtual void Collect(uint32_t reason); // DONE
|
||||||
|
|
||||||
// This returns the singleton nsCycleCollectionParticipant for JSContexts.
|
// This returns the singleton nsCycleCollectionParticipant for JSContexts.
|
||||||
static nsCycleCollectionParticipant *JSContextParticipant();
|
static nsCycleCollectionParticipant *JSContextParticipant();
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "jsprf.h"
|
#include "jsprf.h"
|
||||||
#include "nsCycleCollectionNoteRootCallback.h"
|
#include "nsCycleCollectionNoteRootCallback.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
#include "nsDOMJSUtils.h"
|
||||||
#include "nsLayoutStatics.h"
|
#include "nsLayoutStatics.h"
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
|
|
||||||
@ -829,6 +830,36 @@ CycleCollectedJSRuntime::BeginCycleCollection(nsCycleCollectionNoteRootCallback
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if there exists a JSContext with a default global whose current
|
||||||
|
* inner is gray. The intent is to look for JS Object windows. We don't merge
|
||||||
|
* system compartments, so we don't use them to trigger merging CCs.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
CycleCollectedJSRuntime::UsefulToMergeZones() const
|
||||||
|
{
|
||||||
|
JSContext* iter = nullptr;
|
||||||
|
JSContext* cx;
|
||||||
|
while ((cx = JS_ContextIterator(mJSRuntime, &iter))) {
|
||||||
|
// Skip anything without an nsIScriptContext, as well as any scx whose
|
||||||
|
// NativeGlobal() is not an outer window (this happens with XUL Prototype
|
||||||
|
// compilation scopes, for example, which we're not interested in).
|
||||||
|
nsIScriptContext* scx = GetScriptContextFromJSContext(cx);
|
||||||
|
JS::RootedObject global(cx, scx ? scx->GetNativeGlobal() : nullptr);
|
||||||
|
if (!global || !js::GetObjectParent(global)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Grab the inner from the outer.
|
||||||
|
global = JS_ObjectToInnerObject(cx, global);
|
||||||
|
MOZ_ASSERT(!js::GetObjectParent(global));
|
||||||
|
if (JS::GCThingIsMarkedGray(global) &&
|
||||||
|
!js::IsSystemCompartment(js::GetObjectCompartment(global))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CycleCollectedJSRuntime::FixWeakMappingGrayBits() const
|
CycleCollectedJSRuntime::FixWeakMappingGrayBits() const
|
||||||
{
|
{
|
||||||
@ -841,3 +872,56 @@ CycleCollectedJSRuntime::NeedCollect() const
|
|||||||
{
|
{
|
||||||
return !js::AreGCGrayBitsValid(mJSRuntime);
|
return !js::AreGCGrayBitsValid(mJSRuntime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CycleCollectedJSRuntime::Collect(uint32_t aReason) const
|
||||||
|
{
|
||||||
|
// We're dividing JS objects into 2 categories:
|
||||||
|
//
|
||||||
|
// 1. "real" roots, held by the JS engine itself or rooted through the root
|
||||||
|
// and lock JS APIs. Roots from this category are considered black in the
|
||||||
|
// cycle collector, any cycle they participate in is uncollectable.
|
||||||
|
//
|
||||||
|
// 2. roots held by C++ objects that participate in cycle collection,
|
||||||
|
// held by XPConnect (see TraceXPConnectRoots). Roots from this category
|
||||||
|
// are considered grey in the cycle collector, their final color depends
|
||||||
|
// on the objects that hold them.
|
||||||
|
//
|
||||||
|
// Note that if a root is in both categories it is the fact that it is in
|
||||||
|
// category 1 that takes precedence, so it will be considered black.
|
||||||
|
//
|
||||||
|
// During garbage collection we switch to an additional mark color (gray)
|
||||||
|
// when tracing inside TraceNativeRoots. This allows us to walk those
|
||||||
|
// roots later on and add all objects reachable only from them to the
|
||||||
|
// cycle collector.
|
||||||
|
//
|
||||||
|
// Phases:
|
||||||
|
//
|
||||||
|
// 1. marking of the roots in category 1 by having the JS GC do its marking
|
||||||
|
// 2. marking of the roots in category 2 by TraceNativeRoots using an
|
||||||
|
// additional color (gray).
|
||||||
|
// 3. end of GC, GC can sweep its heap
|
||||||
|
//
|
||||||
|
// At some later point, when the cycle collector runs:
|
||||||
|
//
|
||||||
|
// 4. walk gray objects and add them to the cycle collector, cycle collect
|
||||||
|
//
|
||||||
|
// JS objects that are part of cycles the cycle collector breaks will be
|
||||||
|
// collected by the next JS.
|
||||||
|
//
|
||||||
|
// If WantAllTraces() is false the cycle collector will not traverse roots
|
||||||
|
// from category 1 or any JS objects held by them. Any JS objects they hold
|
||||||
|
// will already be marked by the JS GC and will thus be colored black
|
||||||
|
// themselves. Any C++ objects they hold will have a missing (untraversed)
|
||||||
|
// edge from the JS object to the C++ object and so it will be marked black
|
||||||
|
// too. This decreases the number of objects that the cycle collector has to
|
||||||
|
// deal with.
|
||||||
|
// To improve debugging, if WantAllTraces() is true all JS objects are
|
||||||
|
// traversed.
|
||||||
|
|
||||||
|
MOZ_ASSERT(aReason < JS::gcreason::NUM_REASONS);
|
||||||
|
JS::gcreason::Reason gcreason = static_cast<JS::gcreason::Reason>(aReason);
|
||||||
|
|
||||||
|
JS::PrepareForFullGC(mJSRuntime);
|
||||||
|
JS::GCForReason(mJSRuntime, gcreason);
|
||||||
|
}
|
||||||
|
@ -160,8 +160,10 @@ public:
|
|||||||
void NotifyLeaveCycleCollectionThread() const;
|
void NotifyLeaveCycleCollectionThread() const;
|
||||||
void NotifyEnterMainThread() const;
|
void NotifyEnterMainThread() const;
|
||||||
nsresult BeginCycleCollection(nsCycleCollectionNoteRootCallback &aCb);
|
nsresult BeginCycleCollection(nsCycleCollectionNoteRootCallback &aCb);
|
||||||
|
bool UsefulToMergeZones() const;
|
||||||
void FixWeakMappingGrayBits() const;
|
void FixWeakMappingGrayBits() const;
|
||||||
bool NeedCollect() const;
|
bool NeedCollect() const;
|
||||||
|
void Collect(uint32_t reason) const;
|
||||||
|
|
||||||
// XXXkhuey should be private
|
// XXXkhuey should be private
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user