mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Bug 1723715 part 1 - Add GlobalObjectData and use it for emptyGlobalScope. r=jonco
Differential Revision: https://phabricator.services.mozilla.com/D121981
This commit is contained in:
parent
ad486327b2
commit
1c8f0d1a67
@ -186,6 +186,7 @@ struct ClassInfo {
|
||||
MACRO(Objects, MallocHeap, objectsMallocHeapSlots) \
|
||||
MACRO(Objects, MallocHeap, objectsMallocHeapElementsNormal) \
|
||||
MACRO(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \
|
||||
MACRO(Objects, MallocHeap, objectsMallocHeapGlobalData) \
|
||||
MACRO(Objects, MallocHeap, objectsMallocHeapMisc) \
|
||||
MACRO(Objects, NonHeap, objectsNonHeapElementsNormal) \
|
||||
MACRO(Objects, NonHeap, objectsNonHeapElementsShared) \
|
||||
|
@ -143,7 +143,8 @@ enum class GCAbortReason {
|
||||
_(FinalizationRecordVector) \
|
||||
_(ZoneAllocPolicy) \
|
||||
_(SharedArrayRawBuffer) \
|
||||
_(XDRBufferElements)
|
||||
_(XDRBufferElements) \
|
||||
_(GlobalObjectData)
|
||||
|
||||
#define JS_FOR_EACH_MEMORY_USE(_) \
|
||||
JS_FOR_EACH_PUBLIC_MEMORY_USE(_) \
|
||||
|
@ -208,8 +208,8 @@ bool JS::ObjectOpResult::reportError(JSContext* cx, HandleObject obj,
|
||||
if (ErrorTakesObjectArgument(code_)) {
|
||||
JSObject* unwrapped = js::CheckedUnwrapStatic(obj);
|
||||
const char* name = unwrapped ? unwrapped->getClass()->name : "Object";
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, code_,
|
||||
name, propName.get());
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, code_, name,
|
||||
propName.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1798,6 +1798,8 @@ JS_PUBLIC_API void JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global) {
|
||||
// know the global is live.
|
||||
globalRealm->traceGlobal(trc);
|
||||
|
||||
globalObj->traceData(trc);
|
||||
|
||||
if (JSTraceOp trace = globalRealm->creationOptions().getTrace()) {
|
||||
trace(trc, global);
|
||||
}
|
||||
|
@ -650,10 +650,21 @@ GlobalObject* GlobalObject::createInternal(JSContext* cx,
|
||||
if (!emptyGlobalScope) {
|
||||
return nullptr;
|
||||
}
|
||||
global->setReservedSlot(EMPTY_GLOBAL_SCOPE,
|
||||
PrivateGCThingValue(emptyGlobalScope));
|
||||
|
||||
cx->realm()->initGlobal(*global, *lexical);
|
||||
{
|
||||
auto data = cx->make_unique<GlobalObjectData>();
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
data->emptyGlobalScope.init(emptyGlobalScope);
|
||||
|
||||
// Note: it's important for the realm's global to be initialized at the
|
||||
// same time as the global's GlobalObjectData, because we free the global's
|
||||
// data when Realm::global_ is cleared.
|
||||
cx->realm()->initGlobal(*global, *lexical);
|
||||
InitReservedSlot(global, GLOBAL_DATA_SLOT, data.release(),
|
||||
MemoryUse::GlobalObjectData);
|
||||
}
|
||||
|
||||
if (!JSObject::setQualifiedVarObj(cx, global)) {
|
||||
return nullptr;
|
||||
@ -709,9 +720,7 @@ GlobalLexicalEnvironmentObject& GlobalObject::lexicalEnvironment() const {
|
||||
}
|
||||
|
||||
GlobalScope& GlobalObject::emptyGlobalScope() const {
|
||||
const Value& v = getReservedSlot(EMPTY_GLOBAL_SCOPE);
|
||||
MOZ_ASSERT(v.isPrivateGCThing() && v.traceKind() == JS::TraceKind::Scope);
|
||||
return static_cast<Scope*>(v.toGCThing())->as<GlobalScope>();
|
||||
return *data().emptyGlobalScope;
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -1136,3 +1145,13 @@ JSObject* GlobalObject::createAsyncIteratorPrototype(
|
||||
global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*proto));
|
||||
return proto;
|
||||
}
|
||||
|
||||
void GlobalObject::releaseData(JSFreeOp* fop) {
|
||||
GlobalObjectData* data = maybeData();
|
||||
setReservedSlot(GLOBAL_DATA_SLOT, PrivateValue(nullptr));
|
||||
fop->delete_(this, data, MemoryUse::GlobalObjectData);
|
||||
}
|
||||
|
||||
void GlobalObjectData::trace(JSTracer* trc) {
|
||||
TraceEdge(trc, &emptyGlobalScope, "global-empty-scope");
|
||||
}
|
||||
|
@ -54,6 +54,23 @@ class GlobalLexicalEnvironmentObject;
|
||||
class PlainObject;
|
||||
class RegExpStatics;
|
||||
|
||||
// Data attached to a GlobalObject. This is freed when clearing the Realm's
|
||||
// global_ only because this way we don't need to add a finalizer to all
|
||||
// GlobalObject JSClasses.
|
||||
class GlobalObjectData {
|
||||
friend class js::GlobalObject;
|
||||
|
||||
GlobalObjectData(const GlobalObjectData&) = delete;
|
||||
void operator=(const GlobalObjectData&) = delete;
|
||||
|
||||
public:
|
||||
GlobalObjectData() = default;
|
||||
|
||||
HeapPtr<GlobalScope*> emptyGlobalScope;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
/*
|
||||
* Global object slots are reserved as follows:
|
||||
*
|
||||
@ -97,7 +114,7 @@ class GlobalObject : public NativeObject {
|
||||
THROWTYPEERROR,
|
||||
|
||||
/* One-off properties stored after slots for built-ins. */
|
||||
EMPTY_GLOBAL_SCOPE,
|
||||
GLOBAL_DATA_SLOT,
|
||||
ITERATOR_PROTO,
|
||||
ARRAY_ITERATOR_PROTO,
|
||||
STRING_ITERATOR_PROTO,
|
||||
@ -148,10 +165,29 @@ class GlobalObject : public NativeObject {
|
||||
return APPLICATION_SLOTS + JSProto_LIMIT + key;
|
||||
}
|
||||
|
||||
GlobalObjectData* maybeData() {
|
||||
Value v = getReservedSlot(GLOBAL_DATA_SLOT);
|
||||
return static_cast<GlobalObjectData*>(v.toPrivate());
|
||||
}
|
||||
const GlobalObjectData* maybeData() const {
|
||||
Value v = getReservedSlot(GLOBAL_DATA_SLOT);
|
||||
return static_cast<const GlobalObjectData*>(v.toPrivate());
|
||||
}
|
||||
|
||||
GlobalObjectData& data() { return *maybeData(); }
|
||||
const GlobalObjectData& data() const { return *maybeData(); }
|
||||
|
||||
public:
|
||||
GlobalLexicalEnvironmentObject& lexicalEnvironment() const;
|
||||
GlobalScope& emptyGlobalScope() const;
|
||||
|
||||
void traceData(JSTracer* trc) { data().trace(trc); }
|
||||
void releaseData(JSFreeOp* fop);
|
||||
|
||||
size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(maybeData());
|
||||
}
|
||||
|
||||
void setOriginalEval(JSObject* evalobj) {
|
||||
MOZ_ASSERT(getReservedSlot(EVAL).isUndefined());
|
||||
setReservedSlot(EVAL, ObjectValue(*evalobj));
|
||||
|
@ -3573,6 +3573,9 @@ void JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
ArrayBufferObject::addSizeOfExcludingThis(this, mallocSizeOf, info);
|
||||
} else if (is<SharedArrayBufferObject>()) {
|
||||
SharedArrayBufferObject::addSizeOfExcludingThis(this, mallocSizeOf, info);
|
||||
} else if (is<GlobalObject>()) {
|
||||
info->objectsMallocHeapGlobalData +=
|
||||
as<GlobalObject>().sizeOfData(mallocSizeOf);
|
||||
} else if (is<WeakCollectionObject>()) {
|
||||
info->objectsMallocHeapMisc +=
|
||||
as<WeakCollectionObject>().sizeOfExcludingThis(mallocSizeOf);
|
||||
|
@ -362,6 +362,10 @@ void Realm::sweepAfterMinorGC() {
|
||||
void Realm::traceWeakSavedStacks(JSTracer* trc) { savedStacks_.traceWeak(trc); }
|
||||
|
||||
void Realm::traceWeakObjects(JSTracer* trc) {
|
||||
// If the global is dead, free its GlobalObjectData.
|
||||
if (zone_->isGCSweeping() && globalIsAboutToBeFinalized()) {
|
||||
global_.unbarrieredGet()->releaseData(runtime_->defaultFreeOp());
|
||||
}
|
||||
TraceWeakEdge(trc, &global_, "Realm::global_");
|
||||
TraceWeakEdge(trc, &lexicalEnv_, "Realm::lexicalEnv_");
|
||||
}
|
||||
@ -445,6 +449,7 @@ void Realm::purge() {
|
||||
}
|
||||
|
||||
void Realm::clearTables() {
|
||||
global_.unbarrieredGet()->releaseData(runtime_->defaultFreeOp());
|
||||
global_.set(nullptr);
|
||||
lexicalEnv_.set(nullptr);
|
||||
|
||||
|
@ -44,6 +44,7 @@ class JitRealm;
|
||||
|
||||
class AutoRestoreRealmDebugMode;
|
||||
class GlobalObject;
|
||||
class GlobalObjectData;
|
||||
class GlobalLexicalEnvironmentObject;
|
||||
class MapObject;
|
||||
class NonSyntacticLexicalEnvironmentObject;
|
||||
|
@ -1689,6 +1689,12 @@ static void ReportClassStats(const ClassInfo& classInfo, const nsACString& path,
|
||||
"asm.js array buffer elements allocated in the malloc heap.");
|
||||
}
|
||||
|
||||
if (classInfo.objectsMallocHeapGlobalData > 0) {
|
||||
REPORT_BYTES(path + "objects/malloc-heap/global-data"_ns, KIND_HEAP,
|
||||
classInfo.objectsMallocHeapGlobalData,
|
||||
"Data for global objects.");
|
||||
}
|
||||
|
||||
if (classInfo.objectsMallocHeapMisc > 0) {
|
||||
REPORT_BYTES(path + "objects/malloc-heap/misc"_ns, KIND_HEAP,
|
||||
classInfo.objectsMallocHeapMisc, "Miscellaneous object data.");
|
||||
|
Loading…
Reference in New Issue
Block a user