mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1135985 - Use typed members to implement pushMarkStack; r=sfink
This commit is contained in:
parent
98cd9d6d72
commit
773f6b2ed8
@ -7,11 +7,11 @@
|
||||
#include "builtin/SymbolObject.h"
|
||||
|
||||
#include "vm/StringBuffer.h"
|
||||
#include "vm/Symbol.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/Symbol-inl.h"
|
||||
|
||||
using JS::Symbol;
|
||||
using namespace js;
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/Symbol-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
@ -68,37 +67,43 @@ JS_PUBLIC_DATA(void * const) JS::NullPtr::constNullValue = nullptr;
|
||||
*/
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSObject *thing);
|
||||
|
||||
PushMarkStack(GCMarker *gcmarker, JSObject *thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSFunction *thing);
|
||||
|
||||
PushMarkStack(GCMarker *gcmarker, JSFunction *thing) {
|
||||
gcmarker->traverse(static_cast<JSObject *>(thing));
|
||||
}
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSScript *thing);
|
||||
PushMarkStack(GCMarker *gcmarker, ObjectGroup *thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, jit::JitCode *thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSScript *thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, LazyScript *thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, Shape *thing);
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSString *str);
|
||||
|
||||
PushMarkStack(GCMarker *gcmarker, BaseShape *thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JS::Symbol *sym);
|
||||
|
||||
PushMarkStack(GCMarker *gcmarker, JSString *thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, ObjectGroup *thing);
|
||||
PushMarkStack(GCMarker *gcmarker, JS::Symbol *thing);
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
static void MarkChildren(JSTracer *trc, JSString *str);
|
||||
static void MarkChildren(JSTracer *trc, JS::Symbol *sym);
|
||||
static void MarkChildren(JSTracer *trc, JSScript *script);
|
||||
static void MarkChildren(JSTracer *trc, LazyScript *lazy);
|
||||
static void MarkChildren(JSTracer *trc, Shape *shape);
|
||||
static void MarkChildren(JSTracer *trc, BaseShape *base);
|
||||
static void MarkChildren(JSTracer *trc, ObjectGroup *group);
|
||||
static void MarkChildren(JSTracer *trc, jit::JitCode *code);
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
@ -199,7 +204,7 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
|
||||
MOZ_ASSERT_IF(gcMarker->shouldCheckCompartments(),
|
||||
zone->isCollecting() || rt->isAtomsZone(zone));
|
||||
|
||||
MOZ_ASSERT_IF(gcMarker->getMarkColor() == GRAY,
|
||||
MOZ_ASSERT_IF(gcMarker->markColor() == GRAY,
|
||||
!zone->isGCMarkingBlack() || rt->isAtomsZone(zone));
|
||||
|
||||
MOZ_ASSERT(!(zone->isGCSweeping() || zone->isGCFinished() || zone->isGCCompacting()));
|
||||
@ -938,7 +943,7 @@ ShouldMarkCrossCompartment(JSTracer *trc, JSObject *src, Cell *cell)
|
||||
if (!IS_GC_MARKING_TRACER(trc))
|
||||
return true;
|
||||
|
||||
uint32_t color = AsGCMarker(trc)->getMarkColor();
|
||||
uint32_t color = AsGCMarker(trc)->markColor();
|
||||
MOZ_ASSERT(color == BLACK || color == GRAY);
|
||||
|
||||
if (IsInsideNursery(cell)) {
|
||||
@ -1009,27 +1014,6 @@ gc::MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
|
||||
|
||||
/*** Push Mark Stack ***/
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
MOZ_ASSERT((thing)->zone()->isGCMarking())
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT_STR(rt, thing) \
|
||||
MOZ_ASSERT((thing)->zone()->isGCMarking() || \
|
||||
(rt)->isAtomsZone((thing)->zone()));
|
||||
|
||||
// Symbols can also be in the atoms zone.
|
||||
#define JS_COMPARTMENT_ASSERT_SYM(rt, sym) \
|
||||
JS_COMPARTMENT_ASSERT_STR(rt, sym)
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, JSObject *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
if (thing->asTenured().markIfUnmarked(gcmarker->getMarkColor()))
|
||||
gcmarker->pushObject(thing);
|
||||
}
|
||||
|
||||
/*
|
||||
* PushMarkStack for BaseShape unpacks its children directly onto the mark
|
||||
* stack. For a pre-barrier between incremental slices, this may result in
|
||||
@ -1040,61 +1024,10 @@ PushMarkStack(GCMarker *gcmarker, JSObject *thing)
|
||||
static void
|
||||
MaybePushMarkStackBetweenSlices(GCMarker *gcmarker, JSObject *thing)
|
||||
{
|
||||
DebugOnly<JSRuntime *> rt = gcmarker->runtime();
|
||||
JS_COMPARTMENT_ASSERT(rt, thing);
|
||||
MOZ_ASSERT_IF(rt->isHeapBusy(), !IsInsideNursery(thing));
|
||||
MOZ_ASSERT_IF(gcmarker->runtime()->isHeapBusy(), !IsInsideNursery(thing));
|
||||
|
||||
if (!IsInsideNursery(thing) && thing->asTenured().markIfUnmarked(gcmarker->getMarkColor()))
|
||||
gcmarker->pushObject(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
if (thing->asTenured().markIfUnmarked(gcmarker->getMarkColor()))
|
||||
gcmarker->pushObject(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, ObjectGroup *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
gcmarker->pushType(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, JSScript *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/*
|
||||
* We mark scripts directly rather than pushing on the stack as they can
|
||||
* refer to other scripts only indirectly (like via nested functions) and
|
||||
* we cannot get to deep recursion.
|
||||
*/
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
MarkChildren(gcmarker, thing);
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, LazyScript *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/*
|
||||
* We mark lazy scripts directly rather than pushing on the stack as they
|
||||
* only refer to normal scripts and to strings, and cannot recurse.
|
||||
*/
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
MarkChildren(gcmarker, thing);
|
||||
if (!IsInsideNursery(thing))
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1107,20 +1040,10 @@ PushMarkStack(GCMarker *gcmarker, Shape *thing)
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/* We mark shapes directly rather than pushing on the stack. */
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
if (thing->markIfUnmarked(gcmarker->markColor()))
|
||||
ScanShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, jit::JitCode *thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
gcmarker->pushJitCode(thing);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker *gcmarker, BaseShape *base);
|
||||
|
||||
@ -1131,7 +1054,7 @@ PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/* We mark base shapes directly rather than pushing on the stack. */
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
if (thing->markIfUnmarked(gcmarker->markColor()))
|
||||
ScanBaseShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
@ -1154,7 +1077,7 @@ ScanShape(GCMarker *gcmarker, Shape *shape)
|
||||
MaybePushMarkStackBetweenSlices(gcmarker, shape->setterObject());
|
||||
|
||||
shape = shape->previous();
|
||||
if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
if (shape && shape->markIfUnmarked(gcmarker->markColor()))
|
||||
goto restart;
|
||||
}
|
||||
|
||||
@ -1168,7 +1091,7 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
|
||||
if (JSObject *parent = base->getObjectParent()) {
|
||||
MaybePushMarkStackBetweenSlices(gcmarker, parent);
|
||||
} else if (GlobalObject *global = base->compartment()->unsafeUnbarrieredMaybeGlobal()) {
|
||||
PushMarkStack(gcmarker, global);
|
||||
gcmarker->traverse(global);
|
||||
}
|
||||
|
||||
if (JSObject *metadata = base->getObjectMetadata())
|
||||
@ -1182,14 +1105,14 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
|
||||
if (base->isOwned()) {
|
||||
UnownedBaseShape *unowned = base->baseUnowned();
|
||||
MOZ_ASSERT(base->compartment() == unowned->compartment());
|
||||
unowned->markIfUnmarked(gcmarker->getMarkColor());
|
||||
unowned->markIfUnmarked(gcmarker->markColor());
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanLinearString(GCMarker *gcmarker, JSLinearString *str)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime(), str);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), str);
|
||||
MOZ_ASSERT(str->isMarked());
|
||||
|
||||
/*
|
||||
@ -1202,7 +1125,7 @@ ScanLinearString(GCMarker *gcmarker, JSLinearString *str)
|
||||
MOZ_ASSERT(str->JSString::isLinear());
|
||||
if (str->isPermanentAtom())
|
||||
break;
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime(), str);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), str);
|
||||
if (!str->markIfUnmarked())
|
||||
break;
|
||||
}
|
||||
@ -1225,7 +1148,7 @@ ScanRope(GCMarker *gcmarker, JSRope *rope)
|
||||
for (;;) {
|
||||
JS_DIAGNOSTICS_ASSERT(GetGCThingTraceKind(rope) == JSTRACE_STRING);
|
||||
JS_DIAGNOSTICS_ASSERT(rope->JSString::isRope());
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime(), rope);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), rope);
|
||||
MOZ_ASSERT(rope->isMarked());
|
||||
JSRope *next = nullptr;
|
||||
|
||||
@ -1279,7 +1202,7 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
|
||||
if (str->isPermanentAtom())
|
||||
return;
|
||||
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime(), str);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), str);
|
||||
|
||||
/*
|
||||
* As string can only refer to other strings we fully scan its GC graph
|
||||
@ -1304,58 +1227,13 @@ PushMarkStack(GCMarker *gcmarker, JS::Symbol *sym)
|
||||
if (sym->isWellKnownSymbol())
|
||||
return;
|
||||
|
||||
JS_COMPARTMENT_ASSERT_SYM(gcmarker->runtime(), sym);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), sym);
|
||||
MOZ_ASSERT(!IsInsideNursery(sym));
|
||||
|
||||
if (sym->markIfUnmarked())
|
||||
ScanSymbol(gcmarker, sym);
|
||||
}
|
||||
|
||||
void
|
||||
gc::MarkChildren(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
obj->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, JSString *str)
|
||||
{
|
||||
if (str->hasBase())
|
||||
str->markBase(trc);
|
||||
else if (str->isRope())
|
||||
str->asRope().markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, JS::Symbol *sym)
|
||||
{
|
||||
sym->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, JSScript *script)
|
||||
{
|
||||
script->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, LazyScript *lazy)
|
||||
{
|
||||
lazy->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, Shape *shape)
|
||||
{
|
||||
shape->markChildren(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, BaseShape *base)
|
||||
{
|
||||
base->markChildren(trc);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used by the cycle collector to trace through the
|
||||
* children of a BaseShape (and its baseUnowned(), if any). The cycle
|
||||
@ -1424,10 +1302,10 @@ ScanObjectGroup(GCMarker *gcmarker, ObjectGroup *group)
|
||||
}
|
||||
|
||||
if (group->proto().isObject())
|
||||
PushMarkStack(gcmarker, group->proto().toObject());
|
||||
gcmarker->traverse(group->proto().toObject());
|
||||
|
||||
if (group->singleton() && !group->lazy())
|
||||
PushMarkStack(gcmarker, group->singleton());
|
||||
gcmarker->traverse(group->singleton());
|
||||
|
||||
if (group->newScript())
|
||||
group->newScript()->trace(gcmarker);
|
||||
@ -1442,10 +1320,10 @@ ScanObjectGroup(GCMarker *gcmarker, ObjectGroup *group)
|
||||
PushMarkStack(gcmarker, unboxedGroup);
|
||||
|
||||
if (TypeDescr *descr = group->maybeTypeDescr())
|
||||
PushMarkStack(gcmarker, descr);
|
||||
gcmarker->traverse(descr);
|
||||
|
||||
if (JSFunction *fun = group->maybeInterpretedFunction())
|
||||
PushMarkStack(gcmarker, fun);
|
||||
gcmarker->traverse(fun);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1488,12 +1366,6 @@ gc::MarkChildren(JSTracer *trc, ObjectGroup *group)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, jit::JitCode *code)
|
||||
{
|
||||
code->trace(trc);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
PushArenaTyped(GCMarker *gcmarker, ArenaHeader *aheader)
|
||||
@ -1666,9 +1538,9 @@ GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr)
|
||||
if (restoreValueArray(obj, (void **)&vp, (void **)&end))
|
||||
pushValueArray(obj, vp, end);
|
||||
else
|
||||
pushObject(obj);
|
||||
repush(obj);
|
||||
} else if (tag == JitCodeTag) {
|
||||
MarkChildren(this, reinterpret_cast<jit::JitCode *>(addr));
|
||||
reinterpret_cast<jit::JitCode *>(addr)->trace(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1676,7 +1548,7 @@ MOZ_ALWAYS_INLINE void
|
||||
GCMarker::markAndScanString(JSObject *source, JSString *str)
|
||||
{
|
||||
if (!str->isPermanentAtom()) {
|
||||
JS_COMPARTMENT_ASSERT_STR(runtime(), str);
|
||||
JS_COMPARTMENT_ASSERT(runtime(), str);
|
||||
MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone());
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(this, str);
|
||||
@ -1687,21 +1559,13 @@ MOZ_ALWAYS_INLINE void
|
||||
GCMarker::markAndScanSymbol(JSObject *source, JS::Symbol *sym)
|
||||
{
|
||||
if (!sym->isWellKnownSymbol()) {
|
||||
JS_COMPARTMENT_ASSERT_SYM(runtime(), sym);
|
||||
JS_COMPARTMENT_ASSERT(runtime(), sym);
|
||||
MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone());
|
||||
if (sym->markIfUnmarked())
|
||||
ScanSymbol(this, sym);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
GCMarker::markObject(JSObject *source, JSObject *obj)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(runtime(), obj);
|
||||
MOZ_ASSERT(obj->compartment() == source->compartment());
|
||||
return obj->asTenured().markIfUnmarked(getMarkColor());
|
||||
}
|
||||
|
||||
inline void
|
||||
GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
{
|
||||
@ -1756,7 +1620,9 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
markAndScanString(obj, v.toString());
|
||||
} else if (v.isObject()) {
|
||||
JSObject *obj2 = &v.toObject();
|
||||
if (markObject(obj, obj2)) {
|
||||
MOZ_ASSERT(obj->compartment() == obj2->compartment());
|
||||
if (mark(obj2)) {
|
||||
// Save the rest of this value array for later and start scanning obj2's children.N
|
||||
pushValueArray(obj, vp, end);
|
||||
obj = obj2;
|
||||
goto scan_obj;
|
||||
@ -1777,8 +1643,9 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
unboxedTraceList++;
|
||||
while (*unboxedTraceList != -1) {
|
||||
JSObject *obj2 = *reinterpret_cast<JSObject **>(unboxedMemory + *unboxedTraceList);
|
||||
if (obj2 && markObject(obj, obj2))
|
||||
pushObject(obj2);
|
||||
MOZ_ASSERT_IF(obj2, obj->compartment() == obj2->compartment());
|
||||
if (obj2 && mark(obj2))
|
||||
repush(obj2);
|
||||
unboxedTraceList++;
|
||||
}
|
||||
unboxedTraceList++;
|
||||
@ -1788,8 +1655,9 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
markAndScanString(obj, v.toString());
|
||||
} else if (v.isObject()) {
|
||||
JSObject *obj2 = &v.toObject();
|
||||
if (markObject(obj, obj2))
|
||||
pushObject(obj2);
|
||||
MOZ_ASSERT(obj->compartment() == obj2->compartment());
|
||||
if (mark(obj2))
|
||||
repush(obj2);
|
||||
} else if (v.isSymbol()) {
|
||||
markAndScanSymbol(obj, v.toSymbol());
|
||||
}
|
||||
@ -1804,12 +1672,12 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
|
||||
budget.step();
|
||||
if (budget.isOverBudget()) {
|
||||
pushObject(obj);
|
||||
repush(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectGroup *group = obj->groupFromGC();
|
||||
PushMarkStack(this, group);
|
||||
traverse(group);
|
||||
|
||||
Shape *shape = obj->lastProperty();
|
||||
PushMarkStack(this, shape);
|
||||
@ -1855,7 +1723,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
if (nobj->denseElementsAreCopyOnWrite()) {
|
||||
JSObject *owner = nobj->getElementsHeader()->ownerObject();
|
||||
if (owner != nobj) {
|
||||
PushMarkStack(this, owner);
|
||||
traverse(owner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1926,40 +1794,47 @@ GCMarker::drainMarkStack(SliceBudget &budget)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
GCMarker::markChildren(T *thing)
|
||||
{
|
||||
thing->markChildren(this);
|
||||
}
|
||||
|
||||
void
|
||||
js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
MarkChildren(trc, static_cast<JSObject *>(thing));
|
||||
static_cast<JSObject *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkChildren(trc, static_cast<JSScript *>(thing));
|
||||
static_cast<JSScript *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_STRING:
|
||||
MarkChildren(trc, static_cast<JSString *>(thing));
|
||||
static_cast<JSString *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_SYMBOL:
|
||||
MarkChildren(trc, static_cast<JS::Symbol *>(thing));
|
||||
static_cast<JS::Symbol *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkChildren(trc, static_cast<BaseShape *>(thing));
|
||||
static_cast<BaseShape *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
MarkChildren(trc, (js::jit::JitCode *)thing);
|
||||
static_cast<jit::JitCode *>(thing)->trace(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
MarkChildren(trc, static_cast<LazyScript *>(thing));
|
||||
static_cast<LazyScript *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_SHAPE:
|
||||
MarkChildren(trc, static_cast<Shape *>(thing));
|
||||
static_cast<Shape *>(thing)->markChildren(trc);
|
||||
break;
|
||||
|
||||
case JSTRACE_OBJECT_GROUP:
|
||||
@ -1978,6 +1853,23 @@ AssertNonGrayGCThing(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
DebugOnly<Cell *> thing(static_cast<Cell *>(*thingp));
|
||||
MOZ_ASSERT_IF(thing->isTenured(), !thing->asTenured().isMarked(js::gc::GRAY));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
gc::ZoneIsGCMarking(T *thing)
|
||||
{
|
||||
return thing->zone()->isGCMarking();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
js::gc::ZoneIsAtomsZoneForString(JSRuntime *rt, T *thing)
|
||||
{
|
||||
JSGCTraceKind kind = GetGCThingTraceKind(thing);
|
||||
if (kind == JSTRACE_STRING || kind == JSTRACE_SYMBOL)
|
||||
return rt->isAtomsZone(thing->zone());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
|
@ -250,13 +250,6 @@ MarkCrossCompartmentSlot(JSTracer *trc, JSObject *src, HeapValue *dst_slot, cons
|
||||
|
||||
/*** Special Cases ***/
|
||||
|
||||
/*
|
||||
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
|
||||
* JSObject::swap. It should not be considered external interface.
|
||||
*/
|
||||
void
|
||||
MarkChildren(JSTracer *trc, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Trace through the shape and any shapes it contains to mark
|
||||
* non-shape children. This is exposed to the JS API as
|
||||
|
@ -54,7 +54,7 @@ StoreBuffer::WholeCellEdges::mark(JSTracer *trc) const
|
||||
JSObject *object = static_cast<JSObject *>(edge);
|
||||
if (object->is<ArgumentsObject>())
|
||||
ArgumentsObject::trace(trc, object);
|
||||
MarkChildren(trc, object);
|
||||
object->markChildren(trc);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(kind == JSTRACE_JITCODE);
|
||||
|
@ -9,13 +9,16 @@
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "gc/Heap.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "js/TracingAPI.h"
|
||||
|
||||
namespace js {
|
||||
class NativeObject;
|
||||
class BaseShape;
|
||||
class GCMarker;
|
||||
class LazyScript;
|
||||
class NativeObject;
|
||||
class ObjectGroup;
|
||||
namespace gc {
|
||||
struct ArenaHeader;
|
||||
@ -124,6 +127,23 @@ class MarkStack
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
namespace gc {
|
||||
|
||||
template <typename T>
|
||||
extern bool
|
||||
ZoneIsGCMarking(T *thing);
|
||||
|
||||
template <typename T>
|
||||
extern bool
|
||||
ZoneIsAtomsZoneForString(JSRuntime *rt, T *thing);
|
||||
|
||||
} /* namespace gc */
|
||||
#endif
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
MOZ_ASSERT(gc::ZoneIsGCMarking((thing)) || gc::ZoneIsAtomsZoneForString((rt), (thing)))
|
||||
|
||||
class GCMarker : public JSTracer
|
||||
{
|
||||
public:
|
||||
@ -137,21 +157,16 @@ class GCMarker : public JSTracer
|
||||
void stop();
|
||||
void reset();
|
||||
|
||||
void pushObject(JSObject *obj) {
|
||||
pushTaggedPtr(ObjectTag, obj);
|
||||
}
|
||||
|
||||
void pushType(ObjectGroup *group) {
|
||||
pushTaggedPtr(GroupTag, group);
|
||||
}
|
||||
|
||||
void pushJitCode(jit::JitCode *code) {
|
||||
pushTaggedPtr(JitCodeTag, code);
|
||||
}
|
||||
|
||||
uint32_t getMarkColor() const {
|
||||
return color;
|
||||
}
|
||||
// Mark the given GC thing and traverse its children at some point.
|
||||
void traverse(JSObject *thing) { markAndPush(ObjectTag, thing); }
|
||||
void traverse(ObjectGroup *thing) { markAndPush(GroupTag, thing); }
|
||||
void traverse(jit::JitCode *thing) { markAndPush(JitCodeTag, thing); }
|
||||
// The following traverse methods traverse immediately, go out-of-line to do so.
|
||||
void traverse(JSScript *thing) { markAndTraverse(thing); }
|
||||
void traverse(LazyScript *thing) { markAndTraverse(thing); }
|
||||
// The other types are marked immediately and inline via a ScanFoo shared
|
||||
// between PushMarkStack and the processMarkStackTop. Since ScanFoo is
|
||||
// inline in Marking.cpp, we cannot inline it here, yet.
|
||||
|
||||
/*
|
||||
* Care must be taken changing the mark color from gray to black. The cycle
|
||||
@ -165,12 +180,12 @@ class GCMarker : public JSTracer
|
||||
MOZ_ASSERT(color == gc::BLACK);
|
||||
color = gc::GRAY;
|
||||
}
|
||||
|
||||
void setMarkColorBlack() {
|
||||
MOZ_ASSERT(isDrained());
|
||||
MOZ_ASSERT(color == gc::GRAY);
|
||||
color = gc::BLACK;
|
||||
}
|
||||
uint32_t markColor() const { return color; }
|
||||
|
||||
inline void delayMarkingArena(gc::ArenaHeader *aheader);
|
||||
void delayMarkingChildren(const void *thing);
|
||||
@ -230,7 +245,6 @@ class GCMarker : public JSTracer
|
||||
ValueArrayTag,
|
||||
ObjectTag,
|
||||
GroupTag,
|
||||
XmlTag,
|
||||
SavedValueArrayTag,
|
||||
JitCodeTag,
|
||||
LastTag = JitCodeTag
|
||||
@ -240,6 +254,37 @@ class GCMarker : public JSTracer
|
||||
static_assert(StackTagMask >= uintptr_t(LastTag), "The tag mask must subsume the tags.");
|
||||
static_assert(StackTagMask <= gc::CellMask, "The tag mask must be embeddable in a Cell*.");
|
||||
|
||||
// Push an object onto the stack for later tracing and assert that it has
|
||||
// already been marked.
|
||||
void repush(JSObject *obj) {
|
||||
MOZ_ASSERT(gc::TenuredCell::fromPointer(obj)->isMarked(markColor()));
|
||||
pushTaggedPtr(ObjectTag, obj);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void markAndPush(StackTag tag, T *thing) {
|
||||
if (mark(thing))
|
||||
pushTaggedPtr(tag, thing);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void markAndTraverse(T *thing) {
|
||||
if (mark(thing))
|
||||
markChildren(thing);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void markChildren(T *thing);
|
||||
|
||||
// Mark the given GC thing, but do not trace its children. Return true
|
||||
// if the thing became marked.
|
||||
template <typename T>
|
||||
bool mark(T *thing) {
|
||||
JS_COMPARTMENT_ASSERT(runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
|
||||
return gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor());
|
||||
}
|
||||
|
||||
void pushTaggedPtr(StackTag tag, void *ptr) {
|
||||
checkZone(ptr);
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "gc/Marking.h"
|
||||
#include "vm/Symbol.h"
|
||||
#include "vm/Xdr.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
@ -27,7 +28,6 @@
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/Symbol-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
@ -2413,8 +2413,8 @@ JSObject::swap(JSContext *cx, HandleObject a, HandleObject b)
|
||||
*/
|
||||
JS::Zone *zone = a->zone();
|
||||
if (zone->needsIncrementalBarrier()) {
|
||||
MarkChildren(zone->barrierTracer(), a);
|
||||
MarkChildren(zone->barrierTracer(), b);
|
||||
a->markChildren(zone->barrierTracer());
|
||||
b->markChildren(zone->barrierTracer());
|
||||
}
|
||||
|
||||
NotifyGCPostSwap(a, b, r);
|
||||
|
@ -133,13 +133,6 @@ JSRope::new_(js::ExclusiveContext *cx,
|
||||
return str;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSRope::markChildren(JSTracer *trc)
|
||||
{
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u2.left, "left child");
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u3.right, "right child");
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
JSDependentString::init(js::ExclusiveContext *cx, JSLinearString *base, size_t start,
|
||||
size_t length)
|
||||
@ -204,13 +197,6 @@ JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_
|
||||
return str;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSString::markBase(JSTracer *trc)
|
||||
{
|
||||
MOZ_ASSERT(hasBase());
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u3.base, "base");
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
JSFlatString::init(const char16_t *chars, size_t length)
|
||||
{
|
||||
|
@ -459,7 +459,10 @@ class JSString : public js::gc::TenuredCell
|
||||
|
||||
inline JSLinearString *base() const;
|
||||
|
||||
inline void markBase(JSTracer *trc);
|
||||
void markBase(JSTracer *trc) {
|
||||
MOZ_ASSERT(hasBase());
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u3.base, "base");
|
||||
}
|
||||
|
||||
/* Only called by the GC for strings with the FINALIZE_STRING kind. */
|
||||
|
||||
@ -497,6 +500,8 @@ class JSString : public js::gc::TenuredCell
|
||||
bool equals(const char *s);
|
||||
#endif
|
||||
|
||||
inline void markChildren(JSTracer *trc);
|
||||
|
||||
static MOZ_ALWAYS_INLINE void readBarrier(JSString *thing) {
|
||||
if (thing->isPermanentAtom())
|
||||
return;
|
||||
@ -554,22 +559,25 @@ class JSRope : public JSString
|
||||
template <typename CharT>
|
||||
bool copyChars(js::ExclusiveContext *cx, js::ScopedJSFreePtr<CharT> &out) const;
|
||||
|
||||
inline JSString *leftChild() const {
|
||||
JSString *leftChild() const {
|
||||
MOZ_ASSERT(isRope());
|
||||
return d.s.u2.left;
|
||||
}
|
||||
|
||||
inline JSString *rightChild() const {
|
||||
JSString *rightChild() const {
|
||||
MOZ_ASSERT(isRope());
|
||||
return d.s.u3.right;
|
||||
}
|
||||
|
||||
inline void markChildren(JSTracer *trc);
|
||||
void markChildren(JSTracer *trc) {
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u2.left, "left child");
|
||||
js::gc::MarkStringUnbarriered(trc, &d.s.u3.right, "right child");
|
||||
}
|
||||
|
||||
inline static size_t offsetOfLeft() {
|
||||
static size_t offsetOfLeft() {
|
||||
return offsetof(JSRope, d.s.u2.left);
|
||||
}
|
||||
inline static size_t offsetOfRight() {
|
||||
static size_t offsetOfRight() {
|
||||
return offsetof(JSRope, d.s.u3.right);
|
||||
}
|
||||
};
|
||||
@ -1227,6 +1235,15 @@ JSString::base() const
|
||||
return d.s.u3.base;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSString::markChildren(JSTracer *trc)
|
||||
{
|
||||
if (hasBase())
|
||||
markBase(trc);
|
||||
else if (isRope())
|
||||
asRope().markChildren(trc);
|
||||
}
|
||||
|
||||
template<>
|
||||
MOZ_ALWAYS_INLINE const char16_t *
|
||||
JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC &nogc) const
|
||||
|
@ -1,25 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef vm_Symbol_inl_h
|
||||
#define vm_Symbol_inl_h
|
||||
|
||||
#include "vm/Symbol.h"
|
||||
|
||||
#include "gc/Marking.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
|
||||
inline void
|
||||
JS::Symbol::markChildren(JSTracer *trc)
|
||||
{
|
||||
if (description_)
|
||||
MarkStringUnbarriered(trc, &description_, "description");
|
||||
}
|
||||
|
||||
#endif /* vm_Symbol_inl_h */
|
@ -15,6 +15,7 @@
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Marking.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
@ -33,7 +34,11 @@ class Symbol : public js::gc::TenuredCell
|
||||
uint64_t unused2_;
|
||||
|
||||
Symbol(SymbolCode code, JSAtom *desc)
|
||||
: code_(code), description_(desc) {}
|
||||
: code_(code), description_(desc)
|
||||
{
|
||||
// Silence warnings about unused2 being... unused.
|
||||
(void)unused2_;
|
||||
}
|
||||
|
||||
Symbol(const Symbol &) = delete;
|
||||
void operator=(const Symbol &) = delete;
|
||||
@ -51,7 +56,10 @@ class Symbol : public js::gc::TenuredCell
|
||||
bool isWellKnownSymbol() const { return uint32_t(code_) < WellKnownSymbolLimit; }
|
||||
|
||||
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SYMBOL; }
|
||||
inline void markChildren(JSTracer *trc);
|
||||
inline void markChildren(JSTracer *trc) {
|
||||
if (description_)
|
||||
js::gc::MarkStringUnbarriered(trc, &description_, "description");
|
||||
}
|
||||
inline void finalize(js::FreeOp *) {}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user