зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1464134 part 8 - Make IterateHeapUnbarriered and related code use realms instead of compartments. r=jonco
This commit is contained in:
Родитель
732a7c63d6
Коммит
45e968b1dd
|
@ -1196,7 +1196,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void
|
||||
initExtraRealmStats(JSCompartment* aCompartment,
|
||||
initExtraRealmStats(JS::Handle<JS::Realm*> aRealm,
|
||||
JS::RealmStats* aRealmStats)
|
||||
override
|
||||
{
|
||||
|
@ -1208,10 +1208,11 @@ public:
|
|||
|
||||
// This is the |jsPathPrefix|. Each worker has exactly two realms:
|
||||
// one for atoms, and one for everything else.
|
||||
JSCompartment* compartment = JS::GetCompartmentForRealm(aRealm);
|
||||
extras->jsPathPrefix.Assign(mRtPath);
|
||||
extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
|
||||
(void *)js::GetCompartmentZone(aCompartment));
|
||||
extras->jsPathPrefix += js::IsAtomsRealm(JS::GetRealmForCompartment(aCompartment))
|
||||
(void *)js::GetCompartmentZone(compartment));
|
||||
extras->jsPathPrefix += js::IsAtomsRealm(aRealm)
|
||||
? NS_LITERAL_CSTRING("realm(web-worker-atoms)/")
|
||||
: NS_LITERAL_CSTRING("realm(web-worker)/");
|
||||
|
||||
|
|
|
@ -980,7 +980,7 @@ struct RuntimeStats
|
|||
|
||||
mozilla::MallocSizeOf mallocSizeOf_;
|
||||
|
||||
virtual void initExtraRealmStats(JSCompartment* c, RealmStats* rstats) = 0;
|
||||
virtual void initExtraRealmStats(JS::Handle<JS::Realm*> realm, RealmStats* rstats) = 0;
|
||||
virtual void initExtraZoneStats(JS::Zone* zone, ZoneStats* zstats) = 0;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
|
|
|
@ -80,8 +80,8 @@ typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
|
|||
JS::TraceKind traceKind, size_t thingSize);
|
||||
|
||||
/*
|
||||
* This function calls |zoneCallback| on every zone, |compartmentCallback| on
|
||||
* every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
|
||||
* This function calls |zoneCallback| on every zone, |realmCallback| on
|
||||
* every realm, |arenaCallback| on every in-use arena, and |cellCallback|
|
||||
* on every in-use cell in the GC heap.
|
||||
*
|
||||
* Note that no read barrier is triggered on the cells passed to cellCallback,
|
||||
|
@ -90,18 +90,17 @@ typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
|
|||
extern void
|
||||
IterateHeapUnbarriered(JSContext* cx, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
JS::IterateRealmCallback realmCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback);
|
||||
|
||||
/*
|
||||
* This function is like IterateZonesCompartmentsArenasCells, but does it for a
|
||||
* single zone.
|
||||
* This function is like IterateHeapUnbarriered, but does it for a single zone.
|
||||
*/
|
||||
extern void
|
||||
IterateHeapUnbarrieredForZone(JSContext* cx, JS::Zone* zone, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
JS::IterateRealmCallback realmCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback);
|
||||
|
||||
|
|
|
@ -18,13 +18,18 @@ using namespace js;
|
|||
using namespace js::gc;
|
||||
|
||||
static void
|
||||
IterateCompartmentsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
IterateRealmsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
|
||||
JS::IterateRealmCallback realmCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
{
|
||||
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
|
||||
(*compartmentCallback)(cx, data, comp);
|
||||
{
|
||||
Rooted<Realm*> realm(cx);
|
||||
for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
|
||||
realm = r;
|
||||
(*realmCallback)(cx, data, realm);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto thingKind : AllAllocKinds()) {
|
||||
JS::TraceKind traceKind = MapAllocToTraceKind(thingKind);
|
||||
|
@ -42,7 +47,7 @@ IterateCompartmentsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
|
|||
void
|
||||
js::IterateHeapUnbarriered(JSContext* cx, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
JS::IterateRealmCallback realmCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
{
|
||||
|
@ -50,23 +55,23 @@ js::IterateHeapUnbarriered(JSContext* cx, void* data,
|
|||
|
||||
for (ZonesIter zone(cx->runtime(), WithAtoms); !zone.done(); zone.next()) {
|
||||
(*zoneCallback)(cx->runtime(), data, zone);
|
||||
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
|
||||
compartmentCallback, arenaCallback, cellCallback);
|
||||
IterateRealmsArenasCellsUnbarriered(cx, zone, data,
|
||||
realmCallback, arenaCallback, cellCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js::IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
JS::IterateRealmCallback realmCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
{
|
||||
AutoPrepareForTracing prop(cx);
|
||||
|
||||
(*zoneCallback)(cx->runtime(), data, zone);
|
||||
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
|
||||
compartmentCallback, arenaCallback, cellCallback);
|
||||
IterateRealmsArenasCellsUnbarriered(cx, zone, data,
|
||||
realmCallback, arenaCallback, cellCallback);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -139,3 +144,15 @@ JS_IterateCompartments(JSContext* cx, void* data,
|
|||
for (CompartmentsIter c(cx->runtime(), WithAtoms); !c.done(); c.next())
|
||||
(*compartmentCallback)(cx, data, c);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::IterateRealms(JSContext* cx, void* data, JS::IterateRealmCallback realmCallback)
|
||||
{
|
||||
AutoTraceSession session(cx->runtime());
|
||||
|
||||
Rooted<Realm*> realm(cx);
|
||||
for (RealmsIter r(cx->runtime(), WithAtoms); !r.done(); r.next()) {
|
||||
realm = r;
|
||||
(*realmCallback)(cx, data, realm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1098,6 +1098,16 @@ EnterRealm(JSContext* cx, JSObject* target);
|
|||
extern JS_PUBLIC_API(void)
|
||||
LeaveRealm(JSContext* cx, JS::Realm* oldRealm);
|
||||
|
||||
using IterateRealmCallback = void (*)(JSContext* cx, void* data, Handle<Realm*> realm);
|
||||
|
||||
/**
|
||||
* This function calls |realmCallback| on every realm. Beware that there is no
|
||||
* guarantee that the realm will survive after the callback returns. Also,
|
||||
* barriers are disabled via the TraceSession.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
IterateRealms(JSContext* cx, void* data, IterateRealmCallback realmCallback);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data, JSCompartment* compartment);
|
||||
|
|
|
@ -1184,16 +1184,17 @@ DumpHeapVisitZone(JSRuntime* rt, void* data, Zone* zone)
|
|||
}
|
||||
|
||||
static void
|
||||
DumpHeapVisitCompartment(JSContext* cx, void* data, JSCompartment* comp)
|
||||
DumpHeapVisitRealm(JSContext* cx, void* data, Handle<Realm*> realm)
|
||||
{
|
||||
char name[1024];
|
||||
if (cx->runtime()->compartmentNameCallback)
|
||||
(*cx->runtime()->compartmentNameCallback)(cx, comp, name, sizeof(name));
|
||||
if (auto nameCallback = cx->runtime()->realmNameCallback)
|
||||
nameCallback(cx, realm, name, sizeof(name));
|
||||
else
|
||||
strcpy(name, "<unknown>");
|
||||
|
||||
DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
|
||||
fprintf(dtrc->output, "# compartment %s [in zone %p]\n", name, (void*)comp->zone());
|
||||
fprintf(dtrc->output, "# realm %s [in compartment %p, zone %p]\n", name,
|
||||
(void*)realm->compartment(), (void*)realm->zone());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1250,10 +1251,10 @@ js::DumpHeap(JSContext* cx, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehavi
|
|||
|
||||
dtrc.prefix = "> ";
|
||||
IterateHeapUnbarriered(cx, &dtrc,
|
||||
DumpHeapVisitZone,
|
||||
DumpHeapVisitCompartment,
|
||||
DumpHeapVisitArena,
|
||||
DumpHeapVisitCell);
|
||||
DumpHeapVisitZone,
|
||||
DumpHeapVisitRealm,
|
||||
DumpHeapVisitArena,
|
||||
DumpHeapVisitCell);
|
||||
|
||||
fflush(dtrc.output);
|
||||
}
|
||||
|
|
|
@ -332,10 +332,8 @@ StatsZoneCallback(JSRuntime* rt, void* data, Zone* zone)
|
|||
}
|
||||
|
||||
static void
|
||||
StatsRealmCallback(JSContext* cx, void* data, JSCompartment* compartment)
|
||||
StatsRealmCallback(JSContext* cx, void* data, Handle<Realm*> realm)
|
||||
{
|
||||
Realm* realm = JS::GetRealmForCompartment(compartment);
|
||||
|
||||
// Append a new RealmStats to the vector.
|
||||
RuntimeStats* rtStats = static_cast<StatsClosure*>(data)->rtStats;
|
||||
|
||||
|
@ -344,7 +342,7 @@ StatsRealmCallback(JSContext* cx, void* data, JSCompartment* compartment)
|
|||
RealmStats& realmStats = rtStats->realmStatsVector.back();
|
||||
if (!realmStats.initClasses())
|
||||
MOZ_CRASH("oom");
|
||||
rtStats->initExtraRealmStats(compartment, &realmStats);
|
||||
rtStats->initExtraRealmStats(realm, &realmStats);
|
||||
|
||||
realm->setRealmStats(&realmStats);
|
||||
|
||||
|
@ -925,8 +923,7 @@ class SimpleJSRuntimeStats : public JS::RuntimeStats
|
|||
override
|
||||
{}
|
||||
|
||||
virtual void initExtraRealmStats(
|
||||
JSCompartment* c, JS::RealmStats* realmStats) override
|
||||
virtual void initExtraRealmStats(Handle<Realm*> realm, JS::RealmStats* realmStats) override
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -950,10 +947,10 @@ AddSizeOfTab(JSContext* cx, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectP
|
|||
if (!closure.init())
|
||||
return false;
|
||||
IterateHeapUnbarrieredForZone(cx, zone, &closure,
|
||||
StatsZoneCallback,
|
||||
StatsRealmCallback,
|
||||
StatsArenaCallback,
|
||||
StatsCellCallback<CoarseGrained>);
|
||||
StatsZoneCallback,
|
||||
StatsRealmCallback,
|
||||
StatsArenaCallback,
|
||||
StatsCellCallback<CoarseGrained>);
|
||||
|
||||
MOZ_ASSERT(rtStats.zoneStatsVector.length() == 1);
|
||||
rtStats.zTotals.addSizes(rtStats.zoneStatsVector[0]);
|
||||
|
|
|
@ -2043,8 +2043,9 @@ class JSMainRuntimeRealmsReporter final : public nsIMemoryReporter
|
|||
js::Vector<nsCString, 0, js::SystemAllocPolicy> paths;
|
||||
};
|
||||
|
||||
static void CompartmentCallback(JSContext* cx, void* vdata, JSCompartment* c) {
|
||||
static void RealmCallback(JSContext* cx, void* vdata, Handle<Realm*> realm) {
|
||||
// silently ignore OOM errors
|
||||
JSCompartment* c = JS::GetCompartmentForRealm(realm);
|
||||
Data* data = static_cast<Data*>(vdata);
|
||||
nsCString path;
|
||||
GetCompartmentName(c, path, &data->anonymizeID, /* replaceSlashes = */ true);
|
||||
|
@ -2058,19 +2059,18 @@ class JSMainRuntimeRealmsReporter final : public nsIMemoryReporter
|
|||
NS_IMETHOD CollectReports(nsIHandleReportCallback* handleReport,
|
||||
nsISupports* data, bool anonymize) override
|
||||
{
|
||||
// First we collect the compartment paths. Then we report them. Doing
|
||||
// First we collect the realm paths. Then we report them. Doing
|
||||
// the two steps interleaved is a bad idea, because calling
|
||||
// |handleReport| from within CompartmentCallback() leads to all manner
|
||||
// |handleReport| from within RealmCallback() leads to all manner
|
||||
// of assertions.
|
||||
|
||||
Data d;
|
||||
d.anonymizeID = anonymize ? 1 : 0;
|
||||
JS_IterateCompartments(XPCJSContext::Get()->Context(),
|
||||
&d, CompartmentCallback);
|
||||
JS::IterateRealms(XPCJSContext::Get()->Context(), &d, RealmCallback);
|
||||
|
||||
for (size_t i = 0; i < d.paths.length(); i++)
|
||||
REPORT(nsCString(d.paths[i]), KIND_OTHER, UNITS_COUNT, 1,
|
||||
"A live compartment in the main JSRuntime.");
|
||||
"A live realm in the main JSRuntime.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2187,17 +2187,17 @@ class XPCJSRuntimeStats : public JS::RuntimeStats
|
|||
zStats->extra = extras;
|
||||
}
|
||||
|
||||
virtual void initExtraRealmStats(JSCompartment* c,
|
||||
virtual void initExtraRealmStats(Handle<Realm*> realm,
|
||||
JS::RealmStats* realmStats) override
|
||||
{
|
||||
JSCompartment* c = JS::GetCompartmentForRealm(realm);
|
||||
xpc::RealmStatsExtras* extras = new xpc::RealmStatsExtras;
|
||||
nsCString cName;
|
||||
GetCompartmentName(c, cName, &mAnonymizeID, /* replaceSlashes = */ true);
|
||||
|
||||
// Get the compartment's global.
|
||||
// Get the realm's global.
|
||||
AutoSafeJSContext cx;
|
||||
bool needZone = true;
|
||||
Rooted<Realm*> realm(cx, JS::GetRealmForCompartment(c));
|
||||
RootedObject global(cx, JS::GetRealmGlobalOrNull(realm));
|
||||
if (global) {
|
||||
RefPtr<nsGlobalWindowInner> window;
|
||||
|
|
Загрузка…
Ссылка в новой задаче