Bug 1464134 part 8 - Make IterateHeapUnbarriered and related code use realms instead of compartments. r=jonco

This commit is contained in:
Jan de Mooij 2018-05-30 20:14:19 +02:00
Родитель 732a7c63d6
Коммит 45e968b1dd
8 изменённых файлов: 74 добавлений и 49 удалений

Просмотреть файл

@ -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;