зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689413 part 17 - Remove ObjectGroup. r=jonco
Differential Revision: https://phabricator.services.mozilla.com/D106987
This commit is contained in:
Родитель
1eaa0dbe85
Коммит
8f52a7a890
|
@ -542,7 +542,6 @@ struct UnusedGCThingSizes {
|
||||||
MACRO(Other, GCHeapUnused, script) \
|
MACRO(Other, GCHeapUnused, script) \
|
||||||
MACRO(Other, GCHeapUnused, shape) \
|
MACRO(Other, GCHeapUnused, shape) \
|
||||||
MACRO(Other, GCHeapUnused, baseShape) \
|
MACRO(Other, GCHeapUnused, baseShape) \
|
||||||
MACRO(Other, GCHeapUnused, objectGroup) \
|
|
||||||
MACRO(Other, GCHeapUnused, string) \
|
MACRO(Other, GCHeapUnused, string) \
|
||||||
MACRO(Other, GCHeapUnused, symbol) \
|
MACRO(Other, GCHeapUnused, symbol) \
|
||||||
MACRO(Other, GCHeapUnused, bigInt) \
|
MACRO(Other, GCHeapUnused, bigInt) \
|
||||||
|
@ -579,9 +578,6 @@ struct UnusedGCThingSizes {
|
||||||
case JS::TraceKind::JitCode:
|
case JS::TraceKind::JitCode:
|
||||||
jitcode += n;
|
jitcode += n;
|
||||||
break;
|
break;
|
||||||
case JS::TraceKind::ObjectGroup:
|
|
||||||
objectGroup += n;
|
|
||||||
break;
|
|
||||||
case JS::TraceKind::Scope:
|
case JS::TraceKind::Scope:
|
||||||
scope += n;
|
scope += n;
|
||||||
break;
|
break;
|
||||||
|
@ -623,7 +619,6 @@ struct ZoneStats {
|
||||||
MACRO(Other, MallocHeap, bigIntsMallocHeap) \
|
MACRO(Other, MallocHeap, bigIntsMallocHeap) \
|
||||||
MACRO(Other, GCHeapAdmin, gcHeapArenaAdmin) \
|
MACRO(Other, GCHeapAdmin, gcHeapArenaAdmin) \
|
||||||
MACRO(Other, GCHeapUsed, jitCodesGCHeap) \
|
MACRO(Other, GCHeapUsed, jitCodesGCHeap) \
|
||||||
MACRO(Other, GCHeapUsed, objectGroupsGCHeap) \
|
|
||||||
MACRO(Other, GCHeapUsed, scopesGCHeap) \
|
MACRO(Other, GCHeapUsed, scopesGCHeap) \
|
||||||
MACRO(Other, MallocHeap, scopesMallocHeap) \
|
MACRO(Other, MallocHeap, scopesMallocHeap) \
|
||||||
MACRO(Other, GCHeapUsed, regExpSharedsGCHeap) \
|
MACRO(Other, GCHeapUsed, regExpSharedsGCHeap) \
|
||||||
|
|
|
@ -17,7 +17,6 @@ class JSLinearString;
|
||||||
namespace js {
|
namespace js {
|
||||||
class BaseScript;
|
class BaseScript;
|
||||||
class BaseShape;
|
class BaseShape;
|
||||||
class ObjectGroup;
|
|
||||||
class RegExpShared;
|
class RegExpShared;
|
||||||
class Shape;
|
class Shape;
|
||||||
class Scope;
|
class Scope;
|
||||||
|
@ -49,15 +48,12 @@ enum class TraceKind {
|
||||||
// Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
|
// Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
|
||||||
Shape = 0x04,
|
Shape = 0x04,
|
||||||
|
|
||||||
// ObjectGroup details are exposed through
|
BaseShape = 0x05,
|
||||||
// JS_TraceObjectGroupCycleCollectorChildren.
|
|
||||||
ObjectGroup = 0x05,
|
|
||||||
|
|
||||||
// The kind associated with a nullptr.
|
// The kind associated with a nullptr.
|
||||||
Null = 0x06,
|
Null = 0x06,
|
||||||
|
|
||||||
// The following kinds do not have an exposed C++ idiom.
|
// The following kinds do not have an exposed C++ idiom.
|
||||||
BaseShape,
|
|
||||||
JitCode,
|
JitCode,
|
||||||
Script,
|
Script,
|
||||||
Scope,
|
Scope,
|
||||||
|
@ -93,7 +89,6 @@ struct MapTypeToTraceKind {
|
||||||
D(JitCode, js::jit::JitCode, true, false) \
|
D(JitCode, js::jit::JitCode, true, false) \
|
||||||
D(Scope, js::Scope, true, true) \
|
D(Scope, js::Scope, true, true) \
|
||||||
D(Object, JSObject, true, true) \
|
D(Object, JSObject, true, true) \
|
||||||
D(ObjectGroup, js::ObjectGroup, true, false) \
|
|
||||||
D(Script, js::BaseScript, true, true) \
|
D(Script, js::BaseScript, true, true) \
|
||||||
D(Shape, js::Shape, true, false) \
|
D(Shape, js::Shape, true, false) \
|
||||||
D(String, JSString, false, false) \
|
D(String, JSString, false, false) \
|
||||||
|
|
|
@ -250,7 +250,6 @@ class GenericTracer : public JSTracer {
|
||||||
virtual js::BaseScript* onScriptEdge(js::BaseScript* script) = 0;
|
virtual js::BaseScript* onScriptEdge(js::BaseScript* script) = 0;
|
||||||
virtual js::Shape* onShapeEdge(js::Shape* shape) = 0;
|
virtual js::Shape* onShapeEdge(js::Shape* shape) = 0;
|
||||||
virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) = 0;
|
virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) = 0;
|
||||||
virtual js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) = 0;
|
|
||||||
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) = 0;
|
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) = 0;
|
||||||
virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) = 0;
|
virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) = 0;
|
||||||
virtual js::Scope* onScopeEdge(js::Scope* scope) = 0;
|
virtual js::Scope* onScopeEdge(js::Scope* scope) = 0;
|
||||||
|
@ -300,10 +299,6 @@ class JS_PUBLIC_API CallbackTracer : public js::GenericTracer {
|
||||||
onChild(JS::GCCellPtr(shape, JS::TraceKind::Shape));
|
onChild(JS::GCCellPtr(shape, JS::TraceKind::Shape));
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
virtual js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) {
|
|
||||||
onChild(JS::GCCellPtr(group, JS::TraceKind::ObjectGroup));
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) {
|
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) {
|
||||||
onChild(JS::GCCellPtr(base, JS::TraceKind::BaseShape));
|
onChild(JS::GCCellPtr(base, JS::TraceKind::BaseShape));
|
||||||
return base;
|
return base;
|
||||||
|
|
|
@ -16,7 +16,6 @@ namespace js {
|
||||||
|
|
||||||
class ArrayObject;
|
class ArrayObject;
|
||||||
class GlobalObject;
|
class GlobalObject;
|
||||||
class ObjectGroup;
|
|
||||||
|
|
||||||
/* Initialize the String class, returning its prototype object. */
|
/* Initialize the String class, returning its prototype object. */
|
||||||
extern JSObject* InitStringClass(JSContext* cx, Handle<GlobalObject*> global);
|
extern JSObject* InitStringClass(JSContext* cx, Handle<GlobalObject*> global);
|
||||||
|
|
|
@ -64,7 +64,6 @@ namespace gc {
|
||||||
D(SHAPE, Shape, js::Shape, js::Shape, true, false, true) \
|
D(SHAPE, Shape, js::Shape, js::Shape, true, false, true) \
|
||||||
D(ACCESSOR_SHAPE, Shape, js::AccessorShape, js::AccessorShape, true, false, true) \
|
D(ACCESSOR_SHAPE, Shape, js::AccessorShape, js::AccessorShape, true, false, true) \
|
||||||
D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \
|
D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \
|
||||||
D(OBJECT_GROUP, ObjectGroup, js::ObjectGroup, js::ObjectGroup, true, false, true) \
|
|
||||||
D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \
|
D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \
|
||||||
D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, false) \
|
D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, false) \
|
||||||
D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, false) \
|
D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, false) \
|
||||||
|
|
|
@ -1109,7 +1109,6 @@ namespace js {
|
||||||
class ArrayObject;
|
class ArrayObject;
|
||||||
class DebugEnvironmentProxy;
|
class DebugEnvironmentProxy;
|
||||||
class GlobalObject;
|
class GlobalObject;
|
||||||
class ObjectGroup;
|
|
||||||
class PropertyName;
|
class PropertyName;
|
||||||
class Scope;
|
class Scope;
|
||||||
class ScriptSourceObject;
|
class ScriptSourceObject;
|
||||||
|
@ -1136,7 +1135,6 @@ using GCPtrObject = GCPtr<JSObject*>;
|
||||||
using GCPtrScript = GCPtr<JSScript*>;
|
using GCPtrScript = GCPtr<JSScript*>;
|
||||||
using GCPtrString = GCPtr<JSString*>;
|
using GCPtrString = GCPtr<JSString*>;
|
||||||
using GCPtrShape = GCPtr<Shape*>;
|
using GCPtrShape = GCPtr<Shape*>;
|
||||||
using GCPtrObjectGroup = GCPtr<ObjectGroup*>;
|
|
||||||
using GCPtrValue = GCPtr<Value>;
|
using GCPtrValue = GCPtr<Value>;
|
||||||
using GCPtrId = GCPtr<jsid>;
|
using GCPtrId = GCPtr<jsid>;
|
||||||
|
|
||||||
|
@ -1150,7 +1148,6 @@ using WeakHeapPtrScript = WeakHeapPtr<JSScript*>;
|
||||||
using WeakHeapPtrScriptSourceObject = WeakHeapPtr<ScriptSourceObject*>;
|
using WeakHeapPtrScriptSourceObject = WeakHeapPtr<ScriptSourceObject*>;
|
||||||
using WeakHeapPtrShape = WeakHeapPtr<Shape*>;
|
using WeakHeapPtrShape = WeakHeapPtr<Shape*>;
|
||||||
using WeakHeapPtrJitCode = WeakHeapPtr<jit::JitCode*>;
|
using WeakHeapPtrJitCode = WeakHeapPtr<jit::JitCode*>;
|
||||||
using WeakHeapPtrObjectGroup = WeakHeapPtr<ObjectGroup*>;
|
|
||||||
using WeakHeapPtrSymbol = WeakHeapPtr<JS::Symbol*>;
|
using WeakHeapPtrSymbol = WeakHeapPtr<JS::Symbol*>;
|
||||||
using WeakHeapPtrWasmInstanceObject = WeakHeapPtr<WasmInstanceObject*>;
|
using WeakHeapPtrWasmInstanceObject = WeakHeapPtr<WasmInstanceObject*>;
|
||||||
using WeakHeapPtrWasmTableObject = WeakHeapPtr<WasmTableObject*>;
|
using WeakHeapPtrWasmTableObject = WeakHeapPtr<WasmTableObject*>;
|
||||||
|
|
|
@ -25,7 +25,6 @@ struct ClearEdgesTracer final : public GenericTracer {
|
||||||
JS::BigInt* onBigIntEdge(JS::BigInt* bi) override;
|
JS::BigInt* onBigIntEdge(JS::BigInt* bi) override;
|
||||||
js::BaseScript* onScriptEdge(js::BaseScript* script) override;
|
js::BaseScript* onScriptEdge(js::BaseScript* script) override;
|
||||||
js::Shape* onShapeEdge(js::Shape* shape) override;
|
js::Shape* onShapeEdge(js::Shape* shape) override;
|
||||||
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override;
|
|
||||||
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override;
|
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override;
|
||||||
js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) override;
|
js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) override;
|
||||||
js::Scope* onScopeEdge(js::Scope* scope) override;
|
js::Scope* onScopeEdge(js::Scope* scope) override;
|
||||||
|
|
|
@ -401,8 +401,7 @@ static constexpr FinalizePhase BackgroundFinalizePhases[] = {
|
||||||
AllocKind::EXTERNAL_STRING, AllocKind::FAT_INLINE_ATOM, AllocKind::ATOM,
|
AllocKind::EXTERNAL_STRING, AllocKind::FAT_INLINE_ATOM, AllocKind::ATOM,
|
||||||
AllocKind::SYMBOL, AllocKind::BIGINT}},
|
AllocKind::SYMBOL, AllocKind::BIGINT}},
|
||||||
{gcstats::PhaseKind::SWEEP_SHAPE,
|
{gcstats::PhaseKind::SWEEP_SHAPE,
|
||||||
{AllocKind::SHAPE, AllocKind::ACCESSOR_SHAPE, AllocKind::BASE_SHAPE,
|
{AllocKind::SHAPE, AllocKind::ACCESSOR_SHAPE, AllocKind::BASE_SHAPE}}};
|
||||||
AllocKind::OBJECT_GROUP}}};
|
|
||||||
|
|
||||||
void Arena::unmarkAll() {
|
void Arena::unmarkAll() {
|
||||||
MarkBitmapWord* arenaBits = chunk()->markBits.arenaBits(this);
|
MarkBitmapWord* arenaBits = chunk()->markBits.arenaBits(this);
|
||||||
|
@ -2312,9 +2311,6 @@ RegExpShared* MovingTracer::onRegExpSharedEdge(RegExpShared* shared) {
|
||||||
return onEdge(shared);
|
return onEdge(shared);
|
||||||
}
|
}
|
||||||
BigInt* MovingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
|
BigInt* MovingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
|
||||||
ObjectGroup* MovingTracer::onObjectGroupEdge(ObjectGroup* group) {
|
|
||||||
return onEdge(group);
|
|
||||||
}
|
|
||||||
JS::Symbol* MovingTracer::onSymbolEdge(JS::Symbol* sym) {
|
JS::Symbol* MovingTracer::onSymbolEdge(JS::Symbol* sym) {
|
||||||
MOZ_ASSERT(!sym->isForwarded());
|
MOZ_ASSERT(!sym->isForwarded());
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -2599,8 +2595,8 @@ void GCRuntime::updateCellPointers(Zone* zone, AllocKinds kinds) {
|
||||||
|
|
||||||
static constexpr AllocKinds UpdatePhaseOne{
|
static constexpr AllocKinds UpdatePhaseOne{
|
||||||
AllocKind::SCRIPT, AllocKind::BASE_SHAPE, AllocKind::SHAPE,
|
AllocKind::SCRIPT, AllocKind::BASE_SHAPE, AllocKind::SHAPE,
|
||||||
AllocKind::ACCESSOR_SHAPE, AllocKind::OBJECT_GROUP, AllocKind::STRING,
|
AllocKind::ACCESSOR_SHAPE, AllocKind::STRING, AllocKind::JITCODE,
|
||||||
AllocKind::JITCODE, AllocKind::REGEXP_SHARED, AllocKind::SCOPE};
|
AllocKind::REGEXP_SHARED, AllocKind::SCOPE};
|
||||||
|
|
||||||
// UpdatePhaseTwo is typed object descriptor objects.
|
// UpdatePhaseTwo is typed object descriptor objects.
|
||||||
|
|
||||||
|
@ -8040,22 +8036,6 @@ void GCRuntime::mergeRealms(Realm* source, Realm* target) {
|
||||||
MOZ_ASSERT(global);
|
MOZ_ASSERT(global);
|
||||||
AssertTargetIsNotGray(global);
|
AssertTargetIsNotGray(global);
|
||||||
|
|
||||||
for (auto group = source->zone()->cellIterUnsafe<ObjectGroup>();
|
|
||||||
!group.done(); group.next()) {
|
|
||||||
// Replace placeholder object prototypes with the correct prototype in
|
|
||||||
// the target realm.
|
|
||||||
TaggedProto proto(group->protoDeprecated());
|
|
||||||
if (proto.isObject()) {
|
|
||||||
JSObject* obj = proto.toObject();
|
|
||||||
if (GlobalObject::isOffThreadPrototypePlaceholder(obj)) {
|
|
||||||
JSObject* targetProto =
|
|
||||||
global->getPrototypeForOffThreadPlaceholder(obj);
|
|
||||||
MOZ_ASSERT(targetProto->isDelegate());
|
|
||||||
group->setProtoUncheckedDeprecated(TaggedProto(targetProto));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto baseShape = source->zone()->cellIterUnsafe<BaseShape>();
|
for (auto baseShape = source->zone()->cellIterUnsafe<BaseShape>();
|
||||||
!baseShape.done(); baseShape.next()) {
|
!baseShape.done(); baseShape.next()) {
|
||||||
baseShape->setRealmForMergeRealms(target);
|
baseShape->setRealmForMergeRealms(target);
|
||||||
|
@ -8429,7 +8409,6 @@ void GCRuntime::checkHashTablesAfterMovingGC() {
|
||||||
|
|
||||||
for (CompartmentsIter c(this); !c.done(); c.next()) {
|
for (CompartmentsIter c(this); !c.done(); c.next()) {
|
||||||
for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {
|
for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {
|
||||||
r->checkObjectGroupTablesAfterMovingGC();
|
|
||||||
r->dtoaCache.checkCacheAfterMovingGC();
|
r->dtoaCache.checkCacheAfterMovingGC();
|
||||||
if (r->debugEnvs()) {
|
if (r->debugEnvs()) {
|
||||||
r->debugEnvs()->checkHashTablesAfterMovingGC();
|
r->debugEnvs()->checkHashTablesAfterMovingGC();
|
||||||
|
@ -9093,10 +9072,6 @@ js::BaseScript* js::gc::ClearEdgesTracer::onScriptEdge(js::BaseScript* script) {
|
||||||
js::Shape* js::gc::ClearEdgesTracer::onShapeEdge(js::Shape* shape) {
|
js::Shape* js::gc::ClearEdgesTracer::onShapeEdge(js::Shape* shape) {
|
||||||
return onEdge(shape);
|
return onEdge(shape);
|
||||||
}
|
}
|
||||||
js::ObjectGroup* js::gc::ClearEdgesTracer::onObjectGroupEdge(
|
|
||||||
js::ObjectGroup* group) {
|
|
||||||
return onEdge(group);
|
|
||||||
}
|
|
||||||
js::BaseShape* js::gc::ClearEdgesTracer::onBaseShapeEdge(js::BaseShape* base) {
|
js::BaseShape* js::gc::ClearEdgesTracer::onBaseShapeEdge(js::BaseShape* base) {
|
||||||
return onEdge(base);
|
return onEdge(base);
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,6 @@ struct MovingTracer final : public GenericTracer {
|
||||||
Scope* onScopeEdge(Scope* scope) override;
|
Scope* onScopeEdge(Scope* scope) override;
|
||||||
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
||||||
BigInt* onBigIntEdge(BigInt* bi) override;
|
BigInt* onBigIntEdge(BigInt* bi) override;
|
||||||
ObjectGroup* onObjectGroupEdge(ObjectGroup* group) override;
|
|
||||||
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
||||||
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
|
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
|
||||||
|
|
||||||
|
@ -265,7 +264,6 @@ struct SweepingTracer final : public GenericTracer {
|
||||||
Scope* onScopeEdge(Scope* scope) override;
|
Scope* onScopeEdge(Scope* scope) override;
|
||||||
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
||||||
BigInt* onBigIntEdge(BigInt* bi) override;
|
BigInt* onBigIntEdge(BigInt* bi) override;
|
||||||
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override;
|
|
||||||
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -89,7 +89,6 @@ class MarkStack {
|
||||||
enum Tag {
|
enum Tag {
|
||||||
SlotsOrElementsRangeTag,
|
SlotsOrElementsRangeTag,
|
||||||
ObjectTag,
|
ObjectTag,
|
||||||
GroupTag,
|
|
||||||
JitCodeTag,
|
JitCodeTag,
|
||||||
ScriptTag,
|
ScriptTag,
|
||||||
TempRopeTag,
|
TempRopeTag,
|
||||||
|
@ -430,7 +429,6 @@ class GCMarker final : public JSTracer {
|
||||||
void eagerlyMarkChildren(JSString* str);
|
void eagerlyMarkChildren(JSString* str);
|
||||||
void eagerlyMarkChildren(Shape* shape);
|
void eagerlyMarkChildren(Shape* shape);
|
||||||
void eagerlyMarkChildren(Scope* scope);
|
void eagerlyMarkChildren(Scope* scope);
|
||||||
void lazilyMarkChildren(ObjectGroup* group);
|
|
||||||
|
|
||||||
// We may not have concrete types yet, so this has to be outside the header.
|
// We may not have concrete types yet, so this has to be outside the header.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
#include "gc/Heap.h"
|
#include "gc/Heap.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class ObjectGroup;
|
|
||||||
|
|
||||||
namespace gc {
|
namespace gc {
|
||||||
namespace gcprobes {
|
namespace gcprobes {
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,6 @@ class BarrierTracer final : public GenericTracer {
|
||||||
Scope* onScopeEdge(Scope* scope) override;
|
Scope* onScopeEdge(Scope* scope) override;
|
||||||
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
||||||
BigInt* onBigIntEdge(BigInt* bi) override;
|
BigInt* onBigIntEdge(BigInt* bi) override;
|
||||||
ObjectGroup* onObjectGroupEdge(ObjectGroup* group) override;
|
|
||||||
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
|
||||||
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
|
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
|
||||||
|
|
||||||
|
|
|
@ -1112,10 +1112,6 @@ void GCMarker::traverse(JSObject* thing) {
|
||||||
pushThing(thing);
|
pushThing(thing);
|
||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
void GCMarker::traverse(ObjectGroup* thing) {
|
|
||||||
pushThing(thing);
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
void GCMarker::traverse(jit::JitCode* thing) {
|
void GCMarker::traverse(jit::JitCode* thing) {
|
||||||
pushThing(thing);
|
pushThing(thing);
|
||||||
}
|
}
|
||||||
|
@ -1559,18 +1555,6 @@ inline void js::GCMarker::eagerlyMarkChildren(Scope* scope) {
|
||||||
} while (scope && mark(scope));
|
} while (scope && mark(scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
void js::ObjectGroup::traceChildren(JSTracer* trc) {
|
|
||||||
if (protoDeprecated().isObject()) {
|
|
||||||
TraceEdge(trc, &protoDeprecated(), "group_proto");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void js::GCMarker::lazilyMarkChildren(ObjectGroup* group) {
|
|
||||||
if (group->protoDeprecated().isObject()) {
|
|
||||||
markAndTraverseEdge(group, group->protoDeprecated().toObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseShape::traceChildren(JSTracer* trc) {
|
void BaseShape::traceChildren(JSTracer* trc) {
|
||||||
// Note: the realm's global can be nullptr if we GC while creating the global.
|
// Note: the realm's global can be nullptr if we GC while creating the global.
|
||||||
if (JSObject* global = realm()->unsafeUnbarrieredMaybeGlobal()) {
|
if (JSObject* global = realm()->unsafeUnbarrieredMaybeGlobal()) {
|
||||||
|
@ -1947,11 +1931,6 @@ inline void GCMarker::processMarkStackTop(SliceBudget& budget) {
|
||||||
goto scan_obj;
|
goto scan_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MarkStack::GroupTag: {
|
|
||||||
auto group = stack.popPtr().as<ObjectGroup>();
|
|
||||||
return lazilyMarkChildren(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MarkStack::JitCodeTag: {
|
case MarkStack::JitCodeTag: {
|
||||||
auto code = stack.popPtr().as<jit::JitCode>();
|
auto code = stack.popPtr().as<jit::JitCode>();
|
||||||
AutoSetTracingSource asts(this, code);
|
AutoSetTracingSource asts(this, code);
|
||||||
|
@ -2090,10 +2069,6 @@ struct MapTypeToMarkStackTag<JSObject*> {
|
||||||
static const auto value = MarkStack::ObjectTag;
|
static const auto value = MarkStack::ObjectTag;
|
||||||
};
|
};
|
||||||
template <>
|
template <>
|
||||||
struct MapTypeToMarkStackTag<ObjectGroup*> {
|
|
||||||
static const auto value = MarkStack::GroupTag;
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct MapTypeToMarkStackTag<jit::JitCode*> {
|
struct MapTypeToMarkStackTag<jit::JitCode*> {
|
||||||
static const auto value = MarkStack::JitCodeTag;
|
static const auto value = MarkStack::JitCodeTag;
|
||||||
};
|
};
|
||||||
|
@ -2861,9 +2836,6 @@ js::Shape* TenuringTracer::onShapeEdge(Shape* shape) { return shape; }
|
||||||
js::RegExpShared* TenuringTracer::onRegExpSharedEdge(RegExpShared* shared) {
|
js::RegExpShared* TenuringTracer::onRegExpSharedEdge(RegExpShared* shared) {
|
||||||
return shared;
|
return shared;
|
||||||
}
|
}
|
||||||
js::ObjectGroup* TenuringTracer::onObjectGroupEdge(ObjectGroup* group) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
js::BaseShape* TenuringTracer::onBaseShapeEdge(BaseShape* base) { return base; }
|
js::BaseShape* TenuringTracer::onBaseShapeEdge(BaseShape* base) { return base; }
|
||||||
js::jit::JitCode* TenuringTracer::onJitCodeEdge(jit::JitCode* code) {
|
js::jit::JitCode* TenuringTracer::onJitCodeEdge(jit::JitCode* code) {
|
||||||
return code;
|
return code;
|
||||||
|
@ -3902,9 +3874,6 @@ Scope* SweepingTracer::onScopeEdge(Scope* scope) { return onEdge(scope); }
|
||||||
RegExpShared* SweepingTracer::onRegExpSharedEdge(RegExpShared* shared) {
|
RegExpShared* SweepingTracer::onRegExpSharedEdge(RegExpShared* shared) {
|
||||||
return onEdge(shared);
|
return onEdge(shared);
|
||||||
}
|
}
|
||||||
ObjectGroup* SweepingTracer::onObjectGroupEdge(ObjectGroup* group) {
|
|
||||||
return onEdge(group);
|
|
||||||
}
|
|
||||||
BigInt* SweepingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
|
BigInt* SweepingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
|
||||||
JS::Symbol* SweepingTracer::onSymbolEdge(JS::Symbol* sym) {
|
JS::Symbol* SweepingTracer::onSymbolEdge(JS::Symbol* sym) {
|
||||||
return onEdge(sym);
|
return onEdge(sym);
|
||||||
|
@ -4214,10 +4183,6 @@ BigInt* BarrierTracer::onBigIntEdge(BigInt* bi) {
|
||||||
PreWriteBarrier(bi);
|
PreWriteBarrier(bi);
|
||||||
return bi;
|
return bi;
|
||||||
}
|
}
|
||||||
ObjectGroup* BarrierTracer::onObjectGroupEdge(ObjectGroup* group) {
|
|
||||||
PreWriteBarrier(group);
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
JS::Symbol* BarrierTracer::onSymbolEdge(JS::Symbol* sym) {
|
JS::Symbol* BarrierTracer::onSymbolEdge(JS::Symbol* sym) {
|
||||||
PreWriteBarrier(sym);
|
PreWriteBarrier(sym);
|
||||||
return sym;
|
return sym;
|
||||||
|
|
|
@ -24,7 +24,6 @@ namespace js {
|
||||||
class BaseShape;
|
class BaseShape;
|
||||||
class GCMarker;
|
class GCMarker;
|
||||||
class NativeObject;
|
class NativeObject;
|
||||||
class ObjectGroup;
|
|
||||||
class Shape;
|
class Shape;
|
||||||
class WeakMapBase;
|
class WeakMapBase;
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,6 @@ class TenuringTracer final : public GenericTracer {
|
||||||
js::BaseScript* onScriptEdge(BaseScript* script) override;
|
js::BaseScript* onScriptEdge(BaseScript* script) override;
|
||||||
js::Shape* onShapeEdge(Shape* shape) override;
|
js::Shape* onShapeEdge(Shape* shape) override;
|
||||||
js::RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
js::RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
|
||||||
js::ObjectGroup* onObjectGroupEdge(ObjectGroup* group) override;
|
|
||||||
js::BaseShape* onBaseShapeEdge(BaseShape* base) override;
|
js::BaseShape* onBaseShapeEdge(BaseShape* base) override;
|
||||||
js::jit::JitCode* onJitCodeEdge(jit::JitCode* code) override;
|
js::jit::JitCode* onJitCodeEdge(jit::JitCode* code) override;
|
||||||
js::Scope* onScopeEdge(Scope* scope) override;
|
js::Scope* onScopeEdge(Scope* scope) override;
|
||||||
|
|
|
@ -518,10 +518,6 @@ class BufferGrayRootsTracer final : public GenericTracer {
|
||||||
unsupportedEdge();
|
unsupportedEdge();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override {
|
|
||||||
unsupportedEdge();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override {
|
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override {
|
||||||
unsupportedEdge();
|
unsupportedEdge();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -25,7 +25,6 @@ class PlainObject;
|
||||||
class ScriptSourceObject;
|
class ScriptSourceObject;
|
||||||
class SavedFrame;
|
class SavedFrame;
|
||||||
class Shape;
|
class Shape;
|
||||||
class ObjectGroup;
|
|
||||||
class DebuggerArguments;
|
class DebuggerArguments;
|
||||||
class DebuggerEnvironment;
|
class DebuggerEnvironment;
|
||||||
class DebuggerFrame;
|
class DebuggerFrame;
|
||||||
|
@ -39,7 +38,6 @@ class ModuleObject;
|
||||||
|
|
||||||
using HandleNativeObject = JS::Handle<NativeObject*>;
|
using HandleNativeObject = JS::Handle<NativeObject*>;
|
||||||
using HandleShape = JS::Handle<Shape*>;
|
using HandleShape = JS::Handle<Shape*>;
|
||||||
using HandleObjectGroup = JS::Handle<ObjectGroup*>;
|
|
||||||
using HandleAtom = JS::Handle<JSAtom*>;
|
using HandleAtom = JS::Handle<JSAtom*>;
|
||||||
using HandleLinearString = JS::Handle<JSLinearString*>;
|
using HandleLinearString = JS::Handle<JSLinearString*>;
|
||||||
using HandlePropertyName = JS::Handle<PropertyName*>;
|
using HandlePropertyName = JS::Handle<PropertyName*>;
|
||||||
|
@ -74,7 +72,6 @@ using MutableHandleArrayObject = JS::MutableHandle<ArrayObject*>;
|
||||||
|
|
||||||
using RootedNativeObject = JS::Rooted<NativeObject*>;
|
using RootedNativeObject = JS::Rooted<NativeObject*>;
|
||||||
using RootedShape = JS::Rooted<Shape*>;
|
using RootedShape = JS::Rooted<Shape*>;
|
||||||
using RootedObjectGroup = JS::Rooted<ObjectGroup*>;
|
|
||||||
using RootedAtom = JS::Rooted<JSAtom*>;
|
using RootedAtom = JS::Rooted<JSAtom*>;
|
||||||
using RootedLinearString = JS::Rooted<JSLinearString*>;
|
using RootedLinearString = JS::Rooted<JSLinearString*>;
|
||||||
using RootedPropertyName = JS::Rooted<PropertyName*>;
|
using RootedPropertyName = JS::Rooted<PropertyName*>;
|
||||||
|
|
|
@ -116,13 +116,6 @@ void gc::TraceCycleCollectorChildren(JS::CallbackTracer* trc, Shape* shape) {
|
||||||
} while (shape);
|
} while (shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::TraceCycleCollectorChildren(JS::CallbackTracer* trc,
|
|
||||||
ObjectGroup* group) {
|
|
||||||
MOZ_ASSERT(trc->isCallbackTracer());
|
|
||||||
|
|
||||||
group->traceChildren(trc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Traced Edge Printer ****************************************************/
|
/*** Traced Edge Printer ****************************************************/
|
||||||
|
|
||||||
static size_t CountDecimalDigits(size_t num) {
|
static size_t CountDecimalDigits(size_t num) {
|
||||||
|
@ -194,10 +187,6 @@ void js::gc::GetTraceThingInfo(char* buf, size_t bufsize, void* thing,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case JS::TraceKind::ObjectGroup:
|
|
||||||
name = "object_group";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case JS::TraceKind::RegExpShared:
|
case JS::TraceKind::RegExpShared:
|
||||||
name = "reg_exp_shared";
|
name = "reg_exp_shared";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -295,7 +295,6 @@ namespace gc {
|
||||||
// Trace through a shape or group iteratively during cycle collection to avoid
|
// Trace through a shape or group iteratively during cycle collection to avoid
|
||||||
// deep or infinite recursion.
|
// deep or infinite recursion.
|
||||||
void TraceCycleCollectorChildren(JS::CallbackTracer* trc, Shape* shape);
|
void TraceCycleCollectorChildren(JS::CallbackTracer* trc, Shape* shape);
|
||||||
void TraceCycleCollectorChildren(JS::CallbackTracer* trc, ObjectGroup* group);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trace every value within |compartments| that is wrapped by a
|
* Trace every value within |compartments| that is wrapped by a
|
||||||
|
@ -329,10 +328,6 @@ inline js::BaseScript* DispatchToOnEdge(GenericTracer* trc,
|
||||||
inline js::Shape* DispatchToOnEdge(GenericTracer* trc, js::Shape* shape) {
|
inline js::Shape* DispatchToOnEdge(GenericTracer* trc, js::Shape* shape) {
|
||||||
return trc->onShapeEdge(shape);
|
return trc->onShapeEdge(shape);
|
||||||
}
|
}
|
||||||
inline js::ObjectGroup* DispatchToOnEdge(GenericTracer* trc,
|
|
||||||
js::ObjectGroup* group) {
|
|
||||||
return trc->onObjectGroupEdge(group);
|
|
||||||
}
|
|
||||||
inline js::BaseShape* DispatchToOnEdge(GenericTracer* trc,
|
inline js::BaseShape* DispatchToOnEdge(GenericTracer* trc,
|
||||||
js::BaseShape* base) {
|
js::BaseShape* base) {
|
||||||
return trc->onBaseShapeEdge(base);
|
return trc->onBaseShapeEdge(base);
|
||||||
|
|
|
@ -40,10 +40,9 @@ class GCCellPtrTypeCache(object):
|
||||||
"String": "JSString",
|
"String": "JSString",
|
||||||
"Symbol": "JS::Symbol",
|
"Symbol": "JS::Symbol",
|
||||||
"Shape": "js::Shape",
|
"Shape": "js::Shape",
|
||||||
"ObjectGroup": "js::ObjectGroup",
|
"BaseShape": "js::BaseShape",
|
||||||
"Null": "std::nullptr_t",
|
"Null": "std::nullptr_t",
|
||||||
# Out-of-line types.
|
# Out-of-line types.
|
||||||
"BaseShape": "js::BaseShape",
|
|
||||||
"JitCode": "js::jit::JitCode",
|
"JitCode": "js::jit::JitCode",
|
||||||
"Script": "js::BaseScript",
|
"Script": "js::BaseScript",
|
||||||
"Scope": "js::Scope",
|
"Scope": "js::Scope",
|
||||||
|
@ -52,7 +51,6 @@ class GCCellPtrTypeCache(object):
|
||||||
|
|
||||||
# Map from AllocKind to TraceKind for out-of-line types.
|
# Map from AllocKind to TraceKind for out-of-line types.
|
||||||
alloc_map = {
|
alloc_map = {
|
||||||
"BASE_SHAPE": "BaseShape",
|
|
||||||
"JITCODE": "JitCode",
|
"JITCODE": "JitCode",
|
||||||
"SCRIPT": "Script",
|
"SCRIPT": "Script",
|
||||||
"SCOPE": "Scope",
|
"SCOPE": "Scope",
|
||||||
|
|
|
@ -11,7 +11,6 @@ assert_pretty("string", "JS::GCCellPtr((JSString*) )")
|
||||||
assert_pretty("symbol", "JS::GCCellPtr((JS::Symbol*) )")
|
assert_pretty("symbol", "JS::GCCellPtr((JS::Symbol*) )")
|
||||||
assert_pretty("bigint", "JS::GCCellPtr((JS::BigInt*) )")
|
assert_pretty("bigint", "JS::GCCellPtr((JS::BigInt*) )")
|
||||||
assert_pretty("shape", "JS::GCCellPtr((js::Shape*) )")
|
assert_pretty("shape", "JS::GCCellPtr((js::Shape*) )")
|
||||||
assert_pretty("objectGroup", "JS::GCCellPtr((js::ObjectGroup*) )")
|
|
||||||
assert_pretty("baseShape", "JS::GCCellPtr((js::BaseShape*) )")
|
assert_pretty("baseShape", "JS::GCCellPtr((js::BaseShape*) )")
|
||||||
assert_pretty("script", "JS::GCCellPtr((js::BaseScript*) )")
|
assert_pretty("script", "JS::GCCellPtr((js::BaseScript*) )")
|
||||||
assert_pretty("scope", "JS::GCCellPtr((js::Scope*) )")
|
assert_pretty("scope", "JS::GCCellPtr((js::Scope*) )")
|
||||||
|
|
|
@ -183,9 +183,6 @@ int64_t CacheIRCloner::readStubInt64(uint32_t offset) {
|
||||||
Shape* CacheIRCloner::getShapeField(uint32_t stubOffset) {
|
Shape* CacheIRCloner::getShapeField(uint32_t stubOffset) {
|
||||||
return reinterpret_cast<Shape*>(readStubWord(stubOffset));
|
return reinterpret_cast<Shape*>(readStubWord(stubOffset));
|
||||||
}
|
}
|
||||||
ObjectGroup* CacheIRCloner::getGroupField(uint32_t stubOffset) {
|
|
||||||
return reinterpret_cast<ObjectGroup*>(readStubWord(stubOffset));
|
|
||||||
}
|
|
||||||
JSObject* CacheIRCloner::getObjectField(uint32_t stubOffset) {
|
JSObject* CacheIRCloner::getObjectField(uint32_t stubOffset) {
|
||||||
return reinterpret_cast<JSObject*>(readStubWord(stubOffset));
|
return reinterpret_cast<JSObject*>(readStubWord(stubOffset));
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,6 @@ class StubField {
|
||||||
RawInt32,
|
RawInt32,
|
||||||
RawPointer,
|
RawPointer,
|
||||||
Shape,
|
Shape,
|
||||||
ObjectGroup,
|
|
||||||
JSObject,
|
JSObject,
|
||||||
Symbol,
|
Symbol,
|
||||||
String,
|
String,
|
||||||
|
@ -637,10 +636,6 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
|
||||||
assertSameZone(shape);
|
assertSameZone(shape);
|
||||||
addStubField(uintptr_t(shape), StubField::Type::Shape);
|
addStubField(uintptr_t(shape), StubField::Type::Shape);
|
||||||
}
|
}
|
||||||
void writeGroupField(ObjectGroup* group) {
|
|
||||||
MOZ_ASSERT(group);
|
|
||||||
addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
|
|
||||||
}
|
|
||||||
void writeObjectField(JSObject* obj) {
|
void writeObjectField(JSObject* obj) {
|
||||||
MOZ_ASSERT(obj);
|
MOZ_ASSERT(obj);
|
||||||
assertSameCompartment(obj);
|
assertSameCompartment(obj);
|
||||||
|
@ -1221,7 +1216,6 @@ class MOZ_RAII CacheIRCloner {
|
||||||
int64_t readStubInt64(uint32_t offset);
|
int64_t readStubInt64(uint32_t offset);
|
||||||
|
|
||||||
Shape* getShapeField(uint32_t stubOffset);
|
Shape* getShapeField(uint32_t stubOffset);
|
||||||
ObjectGroup* getGroupField(uint32_t stubOffset);
|
|
||||||
JSObject* getObjectField(uint32_t stubOffset);
|
JSObject* getObjectField(uint32_t stubOffset);
|
||||||
JSString* getStringField(uint32_t stubOffset);
|
JSString* getStringField(uint32_t stubOffset);
|
||||||
JSAtom* getAtomField(uint32_t stubOffset);
|
JSAtom* getAtomField(uint32_t stubOffset);
|
||||||
|
|
|
@ -1089,8 +1089,6 @@ GCPtr<T>& CacheIRStubInfo::getStubField(Stub* stub, uint32_t offset) const {
|
||||||
|
|
||||||
template GCPtr<Shape*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
template GCPtr<Shape*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
||||||
ICCacheIRStub* stub, uint32_t offset) const;
|
ICCacheIRStub* stub, uint32_t offset) const;
|
||||||
template GCPtr<ObjectGroup*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
|
||||||
ICCacheIRStub* stub, uint32_t offset) const;
|
|
||||||
template GCPtr<JSObject*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
template GCPtr<JSObject*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
||||||
ICCacheIRStub* stub, uint32_t offset) const;
|
ICCacheIRStub* stub, uint32_t offset) const;
|
||||||
template GCPtr<JSString*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
template GCPtr<JSString*>& CacheIRStubInfo::getStubField<ICCacheIRStub>(
|
||||||
|
@ -1130,9 +1128,6 @@ void CacheIRWriter::copyStubData(uint8_t* dest) const {
|
||||||
case StubField::Type::JSObject:
|
case StubField::Type::JSObject:
|
||||||
InitGCPtr<JSObject*>(destWords, field.asWord());
|
InitGCPtr<JSObject*>(destWords, field.asWord());
|
||||||
break;
|
break;
|
||||||
case StubField::Type::ObjectGroup:
|
|
||||||
InitGCPtr<ObjectGroup*>(destWords, field.asWord());
|
|
||||||
break;
|
|
||||||
case StubField::Type::Symbol:
|
case StubField::Type::Symbol:
|
||||||
InitGCPtr<JS::Symbol*>(destWords, field.asWord());
|
InitGCPtr<JS::Symbol*>(destWords, field.asWord());
|
||||||
break;
|
break;
|
||||||
|
@ -1181,10 +1176,6 @@ void jit::TraceCacheIRStub(JSTracer* trc, T* stub,
|
||||||
TraceSameZoneCrossCompartmentEdge(trc, &shapeField, "cacheir-shape");
|
TraceSameZoneCrossCompartmentEdge(trc, &shapeField, "cacheir-shape");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StubField::Type::ObjectGroup:
|
|
||||||
TraceEdge(trc, &stubInfo->getStubField<T, ObjectGroup*>(stub, offset),
|
|
||||||
"cacheir-group");
|
|
||||||
break;
|
|
||||||
case StubField::Type::JSObject:
|
case StubField::Type::JSObject:
|
||||||
TraceEdge(trc, &stubInfo->getStubField<T, JSObject*>(stub, offset),
|
TraceEdge(trc, &stubInfo->getStubField<T, JSObject*>(stub, offset),
|
||||||
"cacheir-object");
|
"cacheir-object");
|
||||||
|
@ -6783,9 +6774,6 @@ void CacheIRCompiler::emitLoadStubFieldConstant(StubFieldOffset val,
|
||||||
case StubField::Type::String:
|
case StubField::Type::String:
|
||||||
masm.movePtr(ImmGCPtr(stringStubField(val.getOffset())), dest);
|
masm.movePtr(ImmGCPtr(stringStubField(val.getOffset())), dest);
|
||||||
break;
|
break;
|
||||||
case StubField::Type::ObjectGroup:
|
|
||||||
masm.movePtr(ImmGCPtr(groupStubField(val.getOffset())), dest);
|
|
||||||
break;
|
|
||||||
case StubField::Type::JSObject:
|
case StubField::Type::JSObject:
|
||||||
masm.movePtr(ImmGCPtr(objectStubField(val.getOffset())), dest);
|
masm.movePtr(ImmGCPtr(objectStubField(val.getOffset())), dest);
|
||||||
break;
|
break;
|
||||||
|
@ -6818,7 +6806,6 @@ void CacheIRCompiler::emitLoadStubField(StubFieldOffset val, Register dest) {
|
||||||
switch (val.getStubFieldType()) {
|
switch (val.getStubFieldType()) {
|
||||||
case StubField::Type::RawPointer:
|
case StubField::Type::RawPointer:
|
||||||
case StubField::Type::Shape:
|
case StubField::Type::Shape:
|
||||||
case StubField::Type::ObjectGroup:
|
|
||||||
case StubField::Type::JSObject:
|
case StubField::Type::JSObject:
|
||||||
case StubField::Type::Symbol:
|
case StubField::Type::Symbol:
|
||||||
case StubField::Type::String:
|
case StubField::Type::String:
|
||||||
|
|
|
@ -874,10 +874,6 @@ class MOZ_RAII CacheIRCompiler {
|
||||||
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
|
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
|
||||||
return (JS::Symbol*)readStubWord(offset, StubField::Type::Symbol);
|
return (JS::Symbol*)readStubWord(offset, StubField::Type::Symbol);
|
||||||
}
|
}
|
||||||
ObjectGroup* groupStubField(uint32_t offset) {
|
|
||||||
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
|
|
||||||
return (ObjectGroup*)readStubWord(offset, StubField::Type::ObjectGroup);
|
|
||||||
}
|
|
||||||
JS::Compartment* compartmentStubField(uint32_t offset) {
|
JS::Compartment* compartmentStubField(uint32_t offset) {
|
||||||
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
|
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
|
||||||
return (JS::Compartment*)readStubWord(offset, StubField::Type::RawPointer);
|
return (JS::Compartment*)readStubWord(offset, StubField::Type::RawPointer);
|
||||||
|
|
|
@ -76,7 +76,6 @@ arg_writer_info = {
|
||||||
"IntPtrId": ("IntPtrOperandId", "writeOperandId"),
|
"IntPtrId": ("IntPtrOperandId", "writeOperandId"),
|
||||||
"RawId": ("OperandId", "writeOperandId"),
|
"RawId": ("OperandId", "writeOperandId"),
|
||||||
"ShapeField": ("Shape*", "writeShapeField"),
|
"ShapeField": ("Shape*", "writeShapeField"),
|
||||||
"GroupField": ("ObjectGroup*", "writeGroupField"),
|
|
||||||
"ObjectField": ("JSObject*", "writeObjectField"),
|
"ObjectField": ("JSObject*", "writeObjectField"),
|
||||||
"StringField": ("JSString*", "writeStringField"),
|
"StringField": ("JSString*", "writeStringField"),
|
||||||
"AtomField": ("JSAtom*", "writeStringField"),
|
"AtomField": ("JSAtom*", "writeStringField"),
|
||||||
|
@ -171,7 +170,6 @@ arg_reader_info = {
|
||||||
"IntPtrId": ("IntPtrOperandId", "Id", "reader.intPtrOperandId()"),
|
"IntPtrId": ("IntPtrOperandId", "Id", "reader.intPtrOperandId()"),
|
||||||
"RawId": ("uint32_t", "Id", "reader.rawOperandId()"),
|
"RawId": ("uint32_t", "Id", "reader.rawOperandId()"),
|
||||||
"ShapeField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
"ShapeField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
||||||
"GroupField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
|
||||||
"ObjectField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
"ObjectField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
||||||
"StringField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
"StringField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
||||||
"AtomField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
"AtomField": ("uint32_t", "Offset", "reader.stubOffset()"),
|
||||||
|
@ -252,7 +250,6 @@ arg_spewer_method = {
|
||||||
"IntPtrId": "spewOperandId",
|
"IntPtrId": "spewOperandId",
|
||||||
"RawId": "spewRawOperandId",
|
"RawId": "spewRawOperandId",
|
||||||
"ShapeField": "spewField",
|
"ShapeField": "spewField",
|
||||||
"GroupField": "spewField",
|
|
||||||
"ObjectField": "spewField",
|
"ObjectField": "spewField",
|
||||||
"StringField": "spewField",
|
"StringField": "spewField",
|
||||||
"AtomField": "spewField",
|
"AtomField": "spewField",
|
||||||
|
@ -384,7 +381,6 @@ arg_length = {
|
||||||
"IntPtrId": 1,
|
"IntPtrId": 1,
|
||||||
"RawId": 1,
|
"RawId": 1,
|
||||||
"ShapeField": 1,
|
"ShapeField": 1,
|
||||||
"GroupField": 1,
|
|
||||||
"ObjectField": 1,
|
"ObjectField": 1,
|
||||||
"StringField": 1,
|
"StringField": 1,
|
||||||
"AtomField": 1,
|
"AtomField": 1,
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class GenericPrinter;
|
class GenericPrinter;
|
||||||
class ObjectGroup;
|
|
||||||
class PlainObject;
|
class PlainObject;
|
||||||
|
|
||||||
namespace jit {
|
namespace jit {
|
||||||
|
|
|
@ -963,7 +963,6 @@ using CompilerFunction = CompilerGCPointer<JSFunction*>;
|
||||||
using CompilerBaseScript = CompilerGCPointer<BaseScript*>;
|
using CompilerBaseScript = CompilerGCPointer<BaseScript*>;
|
||||||
using CompilerPropertyName = CompilerGCPointer<PropertyName*>;
|
using CompilerPropertyName = CompilerGCPointer<PropertyName*>;
|
||||||
using CompilerShape = CompilerGCPointer<Shape*>;
|
using CompilerShape = CompilerGCPointer<Shape*>;
|
||||||
using CompilerObjectGroup = CompilerGCPointer<ObjectGroup*>;
|
|
||||||
|
|
||||||
// An instruction is an SSA name that is inserted into a basic block's IR
|
// An instruction is an SSA name that is inserted into a basic block's IR
|
||||||
// stream.
|
// stream.
|
||||||
|
|
|
@ -320,11 +320,6 @@ struct TypeToArgProperties<HandleShape> {
|
||||||
TypeToArgProperties<Shape*>::result | VMFunctionData::ByRef;
|
TypeToArgProperties<Shape*>::result | VMFunctionData::ByRef;
|
||||||
};
|
};
|
||||||
template <>
|
template <>
|
||||||
struct TypeToArgProperties<HandleObjectGroup> {
|
|
||||||
static const uint32_t result =
|
|
||||||
TypeToArgProperties<ObjectGroup*>::result | VMFunctionData::ByRef;
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct TypeToArgProperties<HandleBigInt> {
|
struct TypeToArgProperties<HandleBigInt> {
|
||||||
static const uint32_t result =
|
static const uint32_t result =
|
||||||
TypeToArgProperties<BigInt*>::result | VMFunctionData::ByRef;
|
TypeToArgProperties<BigInt*>::result | VMFunctionData::ByRef;
|
||||||
|
@ -379,10 +374,6 @@ struct TypeToRootType<HandleShape> {
|
||||||
static const uint32_t result = VMFunctionData::RootCell;
|
static const uint32_t result = VMFunctionData::RootCell;
|
||||||
};
|
};
|
||||||
template <>
|
template <>
|
||||||
struct TypeToRootType<HandleObjectGroup> {
|
|
||||||
static const uint32_t result = VMFunctionData::RootCell;
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct TypeToRootType<HandleScript> {
|
struct TypeToRootType<HandleScript> {
|
||||||
static const uint32_t result = VMFunctionData::RootCell;
|
static const uint32_t result = VMFunctionData::RootCell;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,6 @@ class GlobalObject;
|
||||||
class InterpreterFrame;
|
class InterpreterFrame;
|
||||||
class LexicalScope;
|
class LexicalScope;
|
||||||
class NativeObject;
|
class NativeObject;
|
||||||
class ObjectGroup;
|
|
||||||
class PropertyName;
|
class PropertyName;
|
||||||
class Shape;
|
class Shape;
|
||||||
class TypedArrayObject;
|
class TypedArrayObject;
|
||||||
|
|
|
@ -141,9 +141,6 @@ class MOZ_RAII WarpCacheIRTranspiler : public WarpBuilderShared {
|
||||||
JS::Symbol* symbolStubField(uint32_t offset) {
|
JS::Symbol* symbolStubField(uint32_t offset) {
|
||||||
return reinterpret_cast<JS::Symbol*>(readStubWord(offset));
|
return reinterpret_cast<JS::Symbol*>(readStubWord(offset));
|
||||||
}
|
}
|
||||||
ObjectGroup* groupStubField(uint32_t offset) {
|
|
||||||
return reinterpret_cast<ObjectGroup*>(readStubWord(offset));
|
|
||||||
}
|
|
||||||
BaseScript* baseScriptStubField(uint32_t offset) {
|
BaseScript* baseScriptStubField(uint32_t offset) {
|
||||||
return reinterpret_cast<BaseScript*>(readStubWord(offset));
|
return reinterpret_cast<BaseScript*>(readStubWord(offset));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1067,10 +1067,6 @@ bool WarpScriptOracle::replaceNurseryPointers(ICCacheIRStub* stub,
|
||||||
static_assert(std::is_convertible_v<Shape*, gc::TenuredCell*>,
|
static_assert(std::is_convertible_v<Shape*, gc::TenuredCell*>,
|
||||||
"Code assumes shapes are tenured");
|
"Code assumes shapes are tenured");
|
||||||
break;
|
break;
|
||||||
case StubField::Type::ObjectGroup:
|
|
||||||
static_assert(std::is_convertible_v<ObjectGroup*, gc::TenuredCell*>,
|
|
||||||
"Code assumes groups are tenured");
|
|
||||||
break;
|
|
||||||
case StubField::Type::Symbol:
|
case StubField::Type::Symbol:
|
||||||
static_assert(std::is_convertible_v<JS::Symbol*, gc::TenuredCell*>,
|
static_assert(std::is_convertible_v<JS::Symbol*, gc::TenuredCell*>,
|
||||||
"Code assumes symbols are tenured");
|
"Code assumes symbols are tenured");
|
||||||
|
|
|
@ -337,11 +337,6 @@ void WarpCacheIR::traceData(JSTracer* trc) {
|
||||||
TraceWarpStubPtr<Shape>(trc, word, "warp-cacheir-shape");
|
TraceWarpStubPtr<Shape>(trc, word, "warp-cacheir-shape");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StubField::Type::ObjectGroup: {
|
|
||||||
uintptr_t word = stubInfo_->getStubRawWord(stubData_, offset);
|
|
||||||
TraceWarpStubPtr<ObjectGroup>(trc, word, "warp-cacheir-group");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StubField::Type::JSObject: {
|
case StubField::Type::JSObject: {
|
||||||
uintptr_t word = stubInfo_->getStubRawWord(stubData_, offset);
|
uintptr_t word = stubInfo_->getStubRawWord(stubData_, offset);
|
||||||
WarpObjectField field = WarpObjectField::fromData(word);
|
WarpObjectField field = WarpObjectField::fromData(word);
|
||||||
|
|
|
@ -184,12 +184,6 @@ JS_FRIEND_API void JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc,
|
||||||
TraceCycleCollectorChildren(trc, &shape.as<Shape>());
|
TraceCycleCollectorChildren(trc, &shape.as<Shape>());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API void JS_TraceObjectGroupCycleCollectorChildren(
|
|
||||||
JS::CallbackTracer* trc, JS::GCCellPtr group) {
|
|
||||||
MOZ_ASSERT(group.is<ObjectGroup>());
|
|
||||||
TraceCycleCollectorChildren(trc, &group.as<ObjectGroup>());
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool DefineHelpProperty(JSContext* cx, HandleObject obj,
|
static bool DefineHelpProperty(JSContext* cx, HandleObject obj,
|
||||||
const char* prop, const char* value) {
|
const char* prop, const char* value) {
|
||||||
RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
|
RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
|
||||||
|
|
|
@ -479,11 +479,6 @@ static void StatsCellCallback(JSRuntime* rt, void* data, JS::GCCellPtr cellptr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case JS::TraceKind::ObjectGroup: {
|
|
||||||
zStats->objectGroupsGCHeap += thingSize;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case JS::TraceKind::Scope: {
|
case JS::TraceKind::Scope: {
|
||||||
Scope* scope = &cellptr.as<Scope>();
|
Scope* scope = &cellptr.as<Scope>();
|
||||||
zStats->scopesGCHeap += thingSize;
|
zStats->scopesGCHeap += thingSize;
|
||||||
|
|
|
@ -35,35 +35,6 @@
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
// ObjectGroup
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static ObjectGroup* MakeGroup(JSContext* cx, Handle<TaggedProto> proto) {
|
|
||||||
MOZ_ASSERT_IF(proto.isObject(),
|
|
||||||
cx->isInsideCurrentCompartment(proto.toObject()));
|
|
||||||
|
|
||||||
ObjectGroup* group = Allocate<ObjectGroup>(cx);
|
|
||||||
if (!group) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
new (group) ObjectGroup(proto);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectGroup::ObjectGroup(TaggedProto proto)
|
|
||||||
: TenuredCellWithNonGCPointer(nullptr), proto_(proto) {
|
|
||||||
/* Windows may not appear on prototype chains. */
|
|
||||||
MOZ_ASSERT_IF(proto.isObject(), !IsWindow(proto.toObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectGroup::setProtoUncheckedDeprecated(TaggedProto proto) {
|
|
||||||
proto_ = proto;
|
|
||||||
MOZ_ASSERT_IF(proto_.isObject() && proto_.toObject()->is<NativeObject>(),
|
|
||||||
proto_.toObject()->isDelegate());
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// GlobalObject
|
// GlobalObject
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
@ -93,139 +64,6 @@ bool GlobalObject::splicePrototype(JSContext* cx, Handle<GlobalObject*> global,
|
||||||
return JSObject::setProtoUnchecked(cx, global, proto);
|
return JSObject::setProtoUnchecked(cx, global, proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
// ObjectGroupRealm NewTable
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Entries for the per-realm set of groups based on prototype and class. An
|
|
||||||
* optional associated object is used which allows multiple groups to be
|
|
||||||
* created with the same prototype. The associated object is a type descriptor
|
|
||||||
* (for typed objects).
|
|
||||||
*/
|
|
||||||
struct ObjectGroupRealm::NewEntry {
|
|
||||||
WeakHeapPtrObjectGroup group;
|
|
||||||
|
|
||||||
explicit NewEntry(ObjectGroup* group) : group(group) {}
|
|
||||||
|
|
||||||
struct Lookup {
|
|
||||||
TaggedProto proto;
|
|
||||||
|
|
||||||
explicit Lookup(TaggedProto proto) : proto(proto) {}
|
|
||||||
|
|
||||||
explicit Lookup(const NewEntry& entry)
|
|
||||||
: proto(entry.group.unbarrieredGet()->protoDeprecated()) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool needsSweep() { return IsAboutToBeFinalized(&group); }
|
|
||||||
|
|
||||||
bool operator==(const NewEntry& other) const { return group == other.group; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
template <>
|
|
||||||
struct MovableCellHasher<ObjectGroupRealm::NewEntry> {
|
|
||||||
using Key = ObjectGroupRealm::NewEntry;
|
|
||||||
using Lookup = ObjectGroupRealm::NewEntry::Lookup;
|
|
||||||
|
|
||||||
static bool hasHash(const Lookup& l) {
|
|
||||||
return MovableCellHasher<TaggedProto>::hasHash(l.proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ensureHash(const Lookup& l) {
|
|
||||||
return MovableCellHasher<TaggedProto>::ensureHash(l.proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline HashNumber hash(const Lookup& lookup) {
|
|
||||||
return MovableCellHasher<TaggedProto>::hash(lookup.proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool match(const ObjectGroupRealm::NewEntry& key,
|
|
||||||
const Lookup& lookup) {
|
|
||||||
TaggedProto proto = key.group.unbarrieredGet()->protoDeprecated();
|
|
||||||
return MovableCellHasher<TaggedProto>::match(proto, lookup.proto);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace js
|
|
||||||
|
|
||||||
class ObjectGroupRealm::NewTable
|
|
||||||
: public JS::WeakCache<js::GCHashSet<NewEntry, MovableCellHasher<NewEntry>,
|
|
||||||
SystemAllocPolicy>> {
|
|
||||||
using Table =
|
|
||||||
js::GCHashSet<NewEntry, MovableCellHasher<NewEntry>, SystemAllocPolicy>;
|
|
||||||
using Base = JS::WeakCache<Table>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit NewTable(Zone* zone) : Base(zone) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* static*/ ObjectGroupRealm& ObjectGroupRealm::getForNewObject(JSContext* cx) {
|
|
||||||
return cx->realm()->objectGroups_;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE ObjectGroup* ObjectGroupRealm::DefaultNewGroupCache::lookup(
|
|
||||||
const JSClass* clasp, TaggedProto proto) {
|
|
||||||
if (group_ && group_->protoDeprecated() == proto) {
|
|
||||||
return group_;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
ObjectGroup* ObjectGroup::defaultNewGroup(JSContext* cx, const JSClass* clasp,
|
|
||||||
TaggedProto proto) {
|
|
||||||
MOZ_ASSERT(clasp);
|
|
||||||
MOZ_ASSERT_IF(proto.isObject(),
|
|
||||||
cx->isInsideCurrentCompartment(proto.toObject()));
|
|
||||||
|
|
||||||
ObjectGroupRealm& groups = ObjectGroupRealm::getForNewObject(cx);
|
|
||||||
|
|
||||||
if (ObjectGroup* group = groups.defaultNewGroupCache.lookup(clasp, proto)) {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc::AutoSuppressGC suppressGC(cx);
|
|
||||||
|
|
||||||
ObjectGroupRealm::NewTable*& table = groups.defaultNewTable;
|
|
||||||
|
|
||||||
if (!table) {
|
|
||||||
table = cx->new_<ObjectGroupRealm::NewTable>(cx->zone());
|
|
||||||
if (!table) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto.isObject() && !proto.toObject()->isDelegate()) {
|
|
||||||
RootedObject protoObj(cx, proto.toObject());
|
|
||||||
if (!JSObject::setDelegate(cx, protoObj)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectGroupRealm::NewTable::AddPtr p =
|
|
||||||
table->lookupForAdd(ObjectGroupRealm::NewEntry::Lookup(proto));
|
|
||||||
if (p) {
|
|
||||||
ObjectGroup* group = p->group;
|
|
||||||
MOZ_ASSERT(group->protoDeprecated() == proto);
|
|
||||||
groups.defaultNewGroupCache.put(group);
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rooted<TaggedProto> protoRoot(cx, proto);
|
|
||||||
ObjectGroup* group = MakeGroup(cx, protoRoot);
|
|
||||||
if (!group) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!table->add(p, ObjectGroupRealm::NewEntry(group))) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
groups.defaultNewGroupCache.put(group);
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool AddPlainObjectProperties(JSContext* cx, HandlePlainObject obj,
|
static bool AddPlainObjectProperties(JSContext* cx, HandlePlainObject obj,
|
||||||
IdValuePair* properties,
|
IdValuePair* properties,
|
||||||
size_t nproperties) {
|
size_t nproperties) {
|
||||||
|
@ -255,80 +93,3 @@ PlainObject* js::NewPlainObjectWithProperties(JSContext* cx,
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
// ObjectGroupRealm
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ObjectGroupRealm::~ObjectGroupRealm() { js_delete(defaultNewTable); }
|
|
||||||
|
|
||||||
void ObjectGroupRealm::addSizeOfExcludingThis(
|
|
||||||
mozilla::MallocSizeOf mallocSizeOf, size_t* realmTables) {
|
|
||||||
if (defaultNewTable) {
|
|
||||||
*realmTables += defaultNewTable->sizeOfIncludingThis(mallocSizeOf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectGroupRealm::clearTables() {
|
|
||||||
if (defaultNewTable) {
|
|
||||||
defaultNewTable->clear();
|
|
||||||
}
|
|
||||||
defaultNewGroupCache.purge();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectGroupRealm::fixupNewTableAfterMovingGC(NewTable* table) {
|
|
||||||
/*
|
|
||||||
* Each entry's hash depends on the object's prototype and we can't tell
|
|
||||||
* whether that has been moved or not in sweepNewObjectGroupTable().
|
|
||||||
*/
|
|
||||||
if (table) {
|
|
||||||
for (NewTable::Enum e(*table); !e.empty(); e.popFront()) {
|
|
||||||
NewEntry& entry = e.mutableFront();
|
|
||||||
|
|
||||||
ObjectGroup* group = entry.group.unbarrieredGet();
|
|
||||||
if (IsForwarded(group)) {
|
|
||||||
group = Forwarded(group);
|
|
||||||
entry.group.set(group);
|
|
||||||
}
|
|
||||||
TaggedProto proto = group->protoDeprecated();
|
|
||||||
if (proto.isObject() && IsForwarded(proto.toObject())) {
|
|
||||||
proto = TaggedProto(Forwarded(proto.toObject()));
|
|
||||||
// Update the group's proto here so that we are able to lookup
|
|
||||||
// entries in this table before all object pointers are updated.
|
|
||||||
group->protoDeprecated() = proto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
|
||||||
|
|
||||||
void ObjectGroupRealm::checkNewTableAfterMovingGC(NewTable* table) {
|
|
||||||
/*
|
|
||||||
* Assert that nothing points into the nursery or needs to be relocated, and
|
|
||||||
* that the hash table entries are discoverable.
|
|
||||||
*/
|
|
||||||
if (!table) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto r = table->all(); !r.empty(); r.popFront()) {
|
|
||||||
NewEntry entry = r.front();
|
|
||||||
CheckGCThingAfterMovingGC(entry.group.unbarrieredGet());
|
|
||||||
TaggedProto proto = entry.group.unbarrieredGet()->protoDeprecated();
|
|
||||||
if (proto.isObject()) {
|
|
||||||
CheckGCThingAfterMovingGC(proto.toObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ptr = table->lookup(NewEntry::Lookup(entry));
|
|
||||||
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // JSGC_HASH_TABLE_CHECKS
|
|
||||||
|
|
||||||
JS::ubi::Node::Size JS::ubi::Concrete<js::ObjectGroup>::size(
|
|
||||||
mozilla::MallocSizeOf mallocSizeOf) const {
|
|
||||||
Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class ObjectGroupRealm;
|
|
||||||
class PlainObject;
|
class PlainObject;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -40,113 +39,6 @@ enum NewObjectKind {
|
||||||
TenuredObject
|
TenuredObject
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: for now just store an int* in the CellHeader. We can't store the Realm*
|
|
||||||
// because it's an incomplete type and we can't include vm/Realm.h here. This
|
|
||||||
// class will be removed shortly anyway.
|
|
||||||
class ObjectGroup : public gc::TenuredCellWithNonGCPointer<int> {
|
|
||||||
/* Prototype shared by objects in this group. */
|
|
||||||
GCPtr<TaggedProto> proto_; // set by constructor
|
|
||||||
|
|
||||||
#ifndef JS_64BIT
|
|
||||||
// Temporary padding to respect MinCellSize.
|
|
||||||
uint64_t padding_ = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// END OF PROPERTIES
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class gc::GCRuntime;
|
|
||||||
|
|
||||||
// See JSObject::offsetOfGroup() comment.
|
|
||||||
friend class js::jit::MacroAssembler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline explicit ObjectGroup(TaggedProto proto);
|
|
||||||
|
|
||||||
const GCPtr<TaggedProto>& protoDeprecated() const { return proto_; }
|
|
||||||
|
|
||||||
GCPtr<TaggedProto>& protoDeprecated() { return proto_; }
|
|
||||||
|
|
||||||
void setProtoUncheckedDeprecated(TaggedProto proto);
|
|
||||||
|
|
||||||
/* Helpers */
|
|
||||||
|
|
||||||
void traceChildren(JSTracer* trc);
|
|
||||||
|
|
||||||
void finalize(JSFreeOp* fop) {
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
|
||||||
|
|
||||||
static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
|
|
||||||
|
|
||||||
static ObjectGroup* defaultNewGroup(JSContext* cx, const JSClass* clasp,
|
|
||||||
TaggedProto proto);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Structure used to manage the groups in a realm.
|
|
||||||
class ObjectGroupRealm {
|
|
||||||
private:
|
|
||||||
class NewTable;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Set of default 'new' groups in the realm.
|
|
||||||
NewTable* defaultNewTable = nullptr;
|
|
||||||
|
|
||||||
// This cache is purged on GC.
|
|
||||||
class DefaultNewGroupCache {
|
|
||||||
ObjectGroup* group_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DefaultNewGroupCache() { purge(); }
|
|
||||||
|
|
||||||
void purge() { group_ = nullptr; }
|
|
||||||
void put(ObjectGroup* group) { group_ = group; }
|
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE ObjectGroup* lookup(const JSClass* clasp,
|
|
||||||
TaggedProto proto);
|
|
||||||
} defaultNewGroupCache = {};
|
|
||||||
|
|
||||||
// END OF PROPERTIES
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class ObjectGroup;
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct NewEntry;
|
|
||||||
|
|
||||||
ObjectGroupRealm() = default;
|
|
||||||
~ObjectGroupRealm();
|
|
||||||
|
|
||||||
ObjectGroupRealm(ObjectGroupRealm&) = delete;
|
|
||||||
void operator=(ObjectGroupRealm&) = delete;
|
|
||||||
|
|
||||||
static ObjectGroupRealm& getForNewObject(JSContext* cx);
|
|
||||||
|
|
||||||
void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
|
||||||
size_t* realmTables);
|
|
||||||
|
|
||||||
void clearTables();
|
|
||||||
|
|
||||||
void purge() { defaultNewGroupCache.purge(); }
|
|
||||||
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
|
||||||
void checkTablesAfterMovingGC() {
|
|
||||||
checkNewTableAfterMovingGC(defaultNewTable);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void fixupTablesAfterMovingGC() {
|
|
||||||
fixupNewTableAfterMovingGC(defaultNewTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
|
||||||
void checkNewTableAfterMovingGC(NewTable* table);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void fixupNewTableAfterMovingGC(NewTable* table);
|
|
||||||
};
|
|
||||||
|
|
||||||
PlainObject* NewPlainObjectWithProperties(JSContext* cx,
|
PlainObject* NewPlainObjectWithProperties(JSContext* cx,
|
||||||
IdValuePair* properties,
|
IdValuePair* properties,
|
||||||
size_t nproperties,
|
size_t nproperties,
|
||||||
|
@ -154,29 +46,4 @@ PlainObject* NewPlainObjectWithProperties(JSContext* cx,
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
// JS::ubi::Nodes can point to object groups; they're js::gc::Cell instances
|
|
||||||
// with no associated compartment.
|
|
||||||
namespace JS {
|
|
||||||
namespace ubi {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class Concrete<js::ObjectGroup> : TracerConcrete<js::ObjectGroup> {
|
|
||||||
protected:
|
|
||||||
explicit Concrete(js::ObjectGroup* ptr)
|
|
||||||
: TracerConcrete<js::ObjectGroup>(ptr) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void construct(void* storage, js::ObjectGroup* ptr) {
|
|
||||||
new (storage) Concrete(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
|
|
||||||
|
|
||||||
const char16_t* typeName() const override { return concreteTypeName; }
|
|
||||||
static const char16_t concreteTypeName[];
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ubi
|
|
||||||
} // namespace JS
|
|
||||||
|
|
||||||
#endif /* vm_ObjectGroup_h */
|
#endif /* vm_ObjectGroup_h */
|
||||||
|
|
|
@ -450,7 +450,6 @@ void Realm::traceWeakTemplateObjects(JSTracer* trc) {
|
||||||
void Realm::fixupAfterMovingGC(JSTracer* trc) {
|
void Realm::fixupAfterMovingGC(JSTracer* trc) {
|
||||||
purge();
|
purge();
|
||||||
fixupGlobal();
|
fixupGlobal();
|
||||||
objectGroups_.fixupTablesAfterMovingGC();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Realm::fixupGlobal() {
|
void Realm::fixupGlobal() {
|
||||||
|
@ -463,7 +462,6 @@ void Realm::fixupGlobal() {
|
||||||
void Realm::purge() {
|
void Realm::purge() {
|
||||||
dtoaCache.purge();
|
dtoaCache.purge();
|
||||||
newProxyCache.purge();
|
newProxyCache.purge();
|
||||||
objectGroups_.purge();
|
|
||||||
objects_.iteratorCache.clearAndCompact();
|
objects_.iteratorCache.clearAndCompact();
|
||||||
arraySpeciesLookup.purge();
|
arraySpeciesLookup.purge();
|
||||||
promiseLookup.purge();
|
promiseLookup.purge();
|
||||||
|
@ -480,7 +478,6 @@ void Realm::clearTables() {
|
||||||
MOZ_ASSERT(!debugEnvs_);
|
MOZ_ASSERT(!debugEnvs_);
|
||||||
MOZ_ASSERT(objects_.enumerators->next() == objects_.enumerators);
|
MOZ_ASSERT(objects_.enumerators->next() == objects_.enumerators);
|
||||||
|
|
||||||
objectGroups_.clearTables();
|
|
||||||
savedStacks_.clear();
|
savedStacks_.clear();
|
||||||
varNames_.clear();
|
varNames_.clear();
|
||||||
}
|
}
|
||||||
|
@ -649,7 +646,6 @@ void Realm::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||||
size_t* nonSyntacticLexicalEnvironmentsArg,
|
size_t* nonSyntacticLexicalEnvironmentsArg,
|
||||||
size_t* jitRealm) {
|
size_t* jitRealm) {
|
||||||
*realmObject += mallocSizeOf(this);
|
*realmObject += mallocSizeOf(this);
|
||||||
objectGroups_.addSizeOfExcludingThis(mallocSizeOf, realmTables);
|
|
||||||
wasm.addSizeOfExcludingThis(mallocSizeOf, realmTables);
|
wasm.addSizeOfExcludingThis(mallocSizeOf, realmTables);
|
||||||
|
|
||||||
objects_.addSizeOfExcludingThis(mallocSizeOf, innerViewsArg,
|
objects_.addSizeOfExcludingThis(mallocSizeOf, innerViewsArg,
|
||||||
|
|
|
@ -314,12 +314,6 @@ class JS::Realm : public JS::shadow::Realm {
|
||||||
js::ObjectRealm objects_;
|
js::ObjectRealm objects_;
|
||||||
friend js::ObjectRealm& js::ObjectRealm::get(const JSObject*);
|
friend js::ObjectRealm& js::ObjectRealm::get(const JSObject*);
|
||||||
|
|
||||||
// Object group tables and other state in the realm. This is private to
|
|
||||||
// enforce use of ObjectGroupRealm::getForNewObject(cx).
|
|
||||||
js::ObjectGroupRealm objectGroups_;
|
|
||||||
friend js::ObjectGroupRealm& js::ObjectGroupRealm::getForNewObject(
|
|
||||||
JSContext* cx);
|
|
||||||
|
|
||||||
// The global environment record's [[VarNames]] list that contains all
|
// The global environment record's [[VarNames]] list that contains all
|
||||||
// names declared using FunctionDeclaration, GeneratorDeclaration, and
|
// names declared using FunctionDeclaration, GeneratorDeclaration, and
|
||||||
// VariableDeclaration declarations in global code in this realm.
|
// VariableDeclaration declarations in global code in this realm.
|
||||||
|
@ -571,12 +565,6 @@ class JS::Realm : public JS::shadow::Realm {
|
||||||
|
|
||||||
void fixupAfterMovingGC(JSTracer* trc);
|
void fixupAfterMovingGC(JSTracer* trc);
|
||||||
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
|
||||||
void checkObjectGroupTablesAfterMovingGC() {
|
|
||||||
objectGroups_.checkTablesAfterMovingGC();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add a name to [[VarNames]]. Reports OOM on failure.
|
// Add a name to [[VarNames]]. Reports OOM on failure.
|
||||||
[[nodiscard]] bool addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name);
|
[[nodiscard]] bool addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name);
|
||||||
void tracekWeakVarNames(JSTracer* trc);
|
void tracekWeakVarNames(JSTracer* trc);
|
||||||
|
|
|
@ -256,7 +256,6 @@ JS::Zone* TracerConcrete<Referent>::zone() const {
|
||||||
template JS::Zone* TracerConcrete<js::BaseScript>::zone() const;
|
template JS::Zone* TracerConcrete<js::BaseScript>::zone() const;
|
||||||
template JS::Zone* TracerConcrete<js::Shape>::zone() const;
|
template JS::Zone* TracerConcrete<js::Shape>::zone() const;
|
||||||
template JS::Zone* TracerConcrete<js::BaseShape>::zone() const;
|
template JS::Zone* TracerConcrete<js::BaseShape>::zone() const;
|
||||||
template JS::Zone* TracerConcrete<js::ObjectGroup>::zone() const;
|
|
||||||
template JS::Zone* TracerConcrete<js::RegExpShared>::zone() const;
|
template JS::Zone* TracerConcrete<js::RegExpShared>::zone() const;
|
||||||
template JS::Zone* TracerConcrete<js::Scope>::zone() const;
|
template JS::Zone* TracerConcrete<js::Scope>::zone() const;
|
||||||
template JS::Zone* TracerConcrete<JS::Symbol>::zone() const;
|
template JS::Zone* TracerConcrete<JS::Symbol>::zone() const;
|
||||||
|
@ -289,8 +288,6 @@ template UniquePtr<EdgeRange> TracerConcrete<js::Shape>::edges(
|
||||||
JSContext* cx, bool wantNames) const;
|
JSContext* cx, bool wantNames) const;
|
||||||
template UniquePtr<EdgeRange> TracerConcrete<js::BaseShape>::edges(
|
template UniquePtr<EdgeRange> TracerConcrete<js::BaseShape>::edges(
|
||||||
JSContext* cx, bool wantNames) const;
|
JSContext* cx, bool wantNames) const;
|
||||||
template UniquePtr<EdgeRange> TracerConcrete<js::ObjectGroup>::edges(
|
|
||||||
JSContext* cx, bool wantNames) const;
|
|
||||||
template UniquePtr<EdgeRange> TracerConcrete<js::RegExpShared>::edges(
|
template UniquePtr<EdgeRange> TracerConcrete<js::RegExpShared>::edges(
|
||||||
JSContext* cx, bool wantNames) const;
|
JSContext* cx, bool wantNames) const;
|
||||||
template UniquePtr<EdgeRange> TracerConcrete<js::Scope>::edges(
|
template UniquePtr<EdgeRange> TracerConcrete<js::Scope>::edges(
|
||||||
|
@ -346,8 +343,6 @@ const char16_t Concrete<js::jit::JitCode>::concreteTypeName[] =
|
||||||
u"js::jit::JitCode";
|
u"js::jit::JitCode";
|
||||||
const char16_t Concrete<js::Shape>::concreteTypeName[] = u"js::Shape";
|
const char16_t Concrete<js::Shape>::concreteTypeName[] = u"js::Shape";
|
||||||
const char16_t Concrete<js::BaseShape>::concreteTypeName[] = u"js::BaseShape";
|
const char16_t Concrete<js::BaseShape>::concreteTypeName[] = u"js::BaseShape";
|
||||||
const char16_t Concrete<js::ObjectGroup>::concreteTypeName[] =
|
|
||||||
u"js::ObjectGroup";
|
|
||||||
const char16_t Concrete<js::Scope>::concreteTypeName[] = u"js::Scope";
|
const char16_t Concrete<js::Scope>::concreteTypeName[] = u"js::Scope";
|
||||||
const char16_t Concrete<js::RegExpShared>::concreteTypeName[] =
|
const char16_t Concrete<js::RegExpShared>::concreteTypeName[] =
|
||||||
u"js::RegExpShared";
|
u"js::RegExpShared";
|
||||||
|
|
|
@ -1405,10 +1405,6 @@ static void ReportZoneStats(const JS::ZoneStats& zStats,
|
||||||
ZRREPORT_GC_BYTES(pathPrefix + "jit-codes-gc-heap"_ns, zStats.jitCodesGCHeap,
|
ZRREPORT_GC_BYTES(pathPrefix + "jit-codes-gc-heap"_ns, zStats.jitCodesGCHeap,
|
||||||
"References to executable code pools used by the JITs.");
|
"References to executable code pools used by the JITs.");
|
||||||
|
|
||||||
ZRREPORT_GC_BYTES(
|
|
||||||
pathPrefix + "object-groups/gc-heap"_ns, zStats.objectGroupsGCHeap,
|
|
||||||
"Classification and type inference information about objects.");
|
|
||||||
|
|
||||||
ZRREPORT_GC_BYTES(pathPrefix + "scopes/gc-heap"_ns, zStats.scopesGCHeap,
|
ZRREPORT_GC_BYTES(pathPrefix + "scopes/gc-heap"_ns, zStats.scopesGCHeap,
|
||||||
"Scope information for scripts.");
|
"Scope information for scripts.");
|
||||||
|
|
||||||
|
@ -2352,12 +2348,6 @@ void JSReporter::CollectReports(WindowPaths* windowPaths,
|
||||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.baseShape,
|
KIND_OTHER, rtStats.zTotals.unusedGCThings.baseShape,
|
||||||
"Unused base shape cells within non-empty arenas.");
|
"Unused base shape cells within non-empty arenas.");
|
||||||
|
|
||||||
REPORT_BYTES(
|
|
||||||
nsLiteralCString(
|
|
||||||
"js-main-runtime-gc-heap-committed/unused/gc-things/object-groups"),
|
|
||||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.objectGroup,
|
|
||||||
"Unused object group cells within non-empty arenas.");
|
|
||||||
|
|
||||||
REPORT_BYTES(nsLiteralCString(
|
REPORT_BYTES(nsLiteralCString(
|
||||||
"js-main-runtime-gc-heap-committed/unused/gc-things/scopes"),
|
"js-main-runtime-gc-heap-committed/unused/gc-things/scopes"),
|
||||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.scope,
|
KIND_OTHER, rtStats.zTotals.unusedGCThings.scope,
|
||||||
|
@ -2419,12 +2409,6 @@ void JSReporter::CollectReports(WindowPaths* windowPaths,
|
||||||
KIND_OTHER, rtStats.zTotals.shapeInfo.shapesGCHeapBase,
|
KIND_OTHER, rtStats.zTotals.shapeInfo.shapesGCHeapBase,
|
||||||
"Used base shape cells.");
|
"Used base shape cells.");
|
||||||
|
|
||||||
MREPORT_BYTES(
|
|
||||||
nsLiteralCString(
|
|
||||||
"js-main-runtime-gc-heap-committed/used/gc-things/object-groups"),
|
|
||||||
KIND_OTHER, rtStats.zTotals.objectGroupsGCHeap,
|
|
||||||
"Used object group cells.");
|
|
||||||
|
|
||||||
MREPORT_BYTES(nsLiteralCString(
|
MREPORT_BYTES(nsLiteralCString(
|
||||||
"js-main-runtime-gc-heap-committed/used/gc-things/scopes"),
|
"js-main-runtime-gc-heap-committed/used/gc-things/scopes"),
|
||||||
KIND_OTHER, rtStats.zTotals.scopesGCHeap, "Used scope cells.");
|
KIND_OTHER, rtStats.zTotals.scopesGCHeap, "Used scope cells.");
|
||||||
|
|
|
@ -428,11 +428,6 @@ void TraversalTracer::onChild(const JS::GCCellPtr& aThing) {
|
||||||
// The maximum depth of traversal when tracing a Shape is unbounded, due to
|
// The maximum depth of traversal when tracing a Shape is unbounded, due to
|
||||||
// the parent pointers on the shape.
|
// the parent pointers on the shape.
|
||||||
JS_TraceShapeCycleCollectorChildren(this, aThing);
|
JS_TraceShapeCycleCollectorChildren(this, aThing);
|
||||||
} else if (aThing.is<js::ObjectGroup>()) {
|
|
||||||
// The maximum depth of traversal when tracing an ObjectGroup is unbounded,
|
|
||||||
// due to information attached to the groups which can lead other groups to
|
|
||||||
// be traced.
|
|
||||||
JS_TraceObjectGroupCycleCollectorChildren(this, aThing);
|
|
||||||
} else {
|
} else {
|
||||||
JS::TraceChildren(this, aThing);
|
JS::TraceChildren(this, aThing);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче