Commit 333feabd authored by Terrence Cole's avatar Terrence Cole
Browse files

Bug 728343 - Make unbarriered object marking interface indirect ; r=billm

This will allow us to move objects that are not wrapped in a HeapPtr.
parent 5b66a08a
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -294,8 +294,10 @@ HeapId::pre()
    if (JS_UNLIKELY(JSID_IS_OBJECT(value))) {
        JSObject *obj = JSID_TO_OBJECT(value);
        JSCompartment *comp = obj->compartment();
        if (comp->needsBarrier())
            js::gc::MarkObjectUnbarriered(comp->barrierTracer(), obj, "write barrier");
        if (comp->needsBarrier()) {
            js::gc::MarkObjectUnbarriered(comp->barrierTracer(), &obj, "write barrier");
            JS_ASSERT(obj == JSID_TO_OBJECT(value));
        }
    }
#endif
}
+3 −1
Original line number Diff line number Diff line
@@ -4264,7 +4264,9 @@ prop_iter_trace(JSTracer *trc, JSObject *obj)
         * barrier here because the pointer is updated via setPrivate, which
         * always takes a barrier.
         */
        MarkShapeUnbarriered(trc, (Shape *)pdata, "prop iter shape");
        Shape *tmp = (Shape *)pdata;
        MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
        obj->setPrivate(tmp);
    } else {
        /* Non-native case: mark each id in the JSIdArray private. */
        JSIdArray *ida = (JSIdArray *) pdata;
+1 −1
Original line number Diff line number Diff line
@@ -1193,7 +1193,7 @@ array_trace(JSTracer *trc, JSObject *obj)
    JS_ASSERT(obj->isDenseArray());

    uint32_t initLength = obj->getDenseArrayInitializedLength();
    MarkSlotRange(trc, initLength, obj->getDenseArrayElements(), "element");
    MarkArraySlots(trc, initLength, obj->getDenseArrayElements(), "element");
}

static JSBool
+5 −5
Original line number Diff line number Diff line
@@ -1094,13 +1094,13 @@ JSFunction::trace(JSTracer *trc)
    }

    if (atom)
        MarkStringUnbarriered(trc, atom, "atom");
        MarkStringUnbarriered(trc, &atom, "atom");

    if (isInterpreted()) {
        if (script())
            MarkScript(trc, &script(), "script");
        if (environment())
            MarkObjectUnbarriered(trc, environment(), "fun_callscope");
        if (u.i.script_)
            MarkScriptUnbarriered(trc, &u.i.script_, "script");
        if (u.i.env_)
            MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
    }
}

+40 −101
Original line number Diff line number Diff line
@@ -126,10 +126,10 @@ MarkInternal(JSTracer *trc, T *thing)

template <typename T>
static void
MarkUnbarriered(JSTracer *trc, T *thing, const char *name)
MarkUnbarriered(JSTracer *trc, T **thingp, const char *name)
{
    JS_SET_TRACING_NAME(trc, name);
    MarkInternal(trc, thing);
    MarkInternal(trc, *thingp);
}

template <typename T>
@@ -186,9 +186,9 @@ Mark##base##Root(JSTracer *trc, type **thingp, const char *name)
}                                                                                                 \
                                                                                                  \
void                                                                                              \
Mark##base##Unbarriered(JSTracer *trc, type *thing, const char *name)                             \
Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name)                           \
{                                                                                                 \
    MarkUnbarriered<type>(trc, thing, name);                                                      \
    MarkUnbarriered<type>(trc, thingp, name);                                                     \
}                                                                                                 \
                                                                                                  \
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name)           \
@@ -202,6 +202,7 @@ void Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *na
}                                                                                                 \

DeclMarkerImpl(BaseShape, BaseShape)
DeclMarkerImpl(BaseShape, UnownedBaseShape)
DeclMarkerImpl(Object, ArgumentsObject)
DeclMarkerImpl(Object, GlobalObject)
DeclMarkerImpl(Object, JSObject)
@@ -366,7 +367,7 @@ MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
}

void
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
{
    for (size_t i = 0; i < len; ++i) {
        JS_SET_TRACING_INDEX(trc, name, i);
@@ -374,6 +375,16 @@ MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
    }
}

void
MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots)
{
    JS_ASSERT(obj->isNative());
    for (uint32_t i = start; i < (start + nslots); ++i) {
        JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
        MarkValueInternal(trc, obj->nativeGetSlotRef(i).unsafeGet());
    }
}

void
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
{
@@ -393,15 +404,11 @@ MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)

/*** Special Marking ***/

/*
 * The unioned HeapPtr stored in script->globalObj needs special treatment to
 * typecheck correctly.
 */
static void
MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const char *name)
void
MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name)
{
    JS_SET_TRACING_NAME(trc, name);
    MarkInternal(trc, thing.get());
    MarkInternal(trc, thingp->get());
}

void
@@ -644,113 +651,34 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
void
MarkChildren(JSTracer *trc, JSObject *obj)
{
    MarkTypeObject(trc, &obj->typeFromGC(), "type");

    Shape *shape = obj->lastProperty();
    MarkShapeUnbarriered(trc, shape, "shape");

    Class *clasp = shape->getObjectClass();
    if (clasp->trace)
        clasp->trace(trc, obj);

    if (shape->isNative()) {
        uint32_t nslots = obj->slotSpan();
        for (uint32_t i = 0; i < nslots; i++) {
            JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
            MarkValueInternal(trc, obj->nativeGetSlotRef(i).unsafeGet());
        }
    }
    obj->markChildren(trc);
}

static void
MarkChildren(JSTracer *trc, JSString *str)
{
    /*
     * We use custom barriers in JSString, so it's safe to use unbarriered
     * marking here.
     */
    if (str->isDependent()) {
        MarkStringUnbarriered(trc, str->asDependent().base(), "base");
    } else if (str->isRope()) {
        JSRope &rope = str->asRope();
        MarkStringUnbarriered(trc, rope.leftChild(), "left child");
        MarkStringUnbarriered(trc, rope.rightChild(), "right child");
    }
    if (str->isDependent())
        str->asDependent().markChildren(trc);
    else if (str->isRope())
        str->asRope().markChildren(trc);
}

static void
MarkChildren(JSTracer *trc, JSScript *script)
{
    CheckScript(script, NULL);

    JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
                 script->compartment() == trc->runtime->gcCheckCompartment);

    for (uint32_t i = 0; i < script->natoms; ++i) {
        if (JSAtom *p = script->atoms[i])
            MarkStringUnbarriered(trc, p, "atom");
    }

    if (JSScript::isValidOffset(script->objectsOffset)) {
        JSObjectArray *objarray = script->objects();
        MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
    }

    if (JSScript::isValidOffset(script->regexpsOffset)) {
        JSObjectArray *objarray = script->regexps();
        MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
    }

    if (JSScript::isValidOffset(script->constOffset)) {
        JSConstArray *constarray = script->consts();
        MarkValueRange(trc, constarray->length, constarray->vector, "consts");
    }

    if (script->function())
        MarkObjectUnbarriered(trc, script->function(), "function");

    if (!script->isCachedEval && script->globalObject)
        MarkObject(trc, script->globalObject, "object");

    if (IS_GC_MARKING_TRACER(trc) && script->filename)
        js_MarkScriptFilename(script->filename);

    script->bindings.trace(trc);

    if (script->types)
        script->types->trace(trc);

    if (script->hasAnyBreakpointsOrStepMode())
        script->markTrapClosures(trc);
    script->markChildren(trc);
}

static void
MarkChildren(JSTracer *trc, Shape *shape)
{
    MarkBaseShapeUnbarriered(trc, shape->base(), "base");
    MarkId(trc, &shape->propidRef(), "propid");
    if (shape->previous())
        MarkShape(trc, &shape->previousRef(), "parent");
}

static inline void
MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base)
{
    if (base->hasGetterObject())
        MarkObjectUnbarriered(trc, base->getterObject(), "getter");
    if (base->hasSetterObject())
        MarkObjectUnbarriered(trc, base->setterObject(), "setter");
    shape->markChildren(trc);
}

static void
MarkChildren(JSTracer *trc, BaseShape *base)
{
    MarkBaseShapeGetterSetter(trc, base);
    if (base->isOwned())
        MarkBaseShapeUnbarriered(trc, base->baseUnowned(), "base");

    if (JSObject *parent = base->getObjectParent())
        MarkObjectUnbarriered(trc, parent, "parent");
    base->markChildren(trc);
}

/*
@@ -773,11 +701,22 @@ MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent
     */
    base->assertConsistency();

    MarkBaseShapeGetterSetter(trc, base);
    if (base->hasGetterObject()) {
        JSObject *tmp = base->getterObject();
        MarkObjectUnbarriered(trc, &tmp, "getter");
        JS_ASSERT(tmp == base->getterObject());
    }

    if (base->hasSetterObject()) {
        JSObject *tmp = base->setterObject();
        MarkObjectUnbarriered(trc, &tmp, "setter");
        JS_ASSERT(tmp == base->setterObject());
    }

    JSObject *parent = base->getObjectParent();
    if (parent && parent != *prevParent) {
        MarkObjectUnbarriered(trc, parent, "parent");
        MarkObjectUnbarriered(trc, &parent, "parent");
        JS_ASSERT(parent == base->getObjectParent());
        *prevParent = parent;
    }
}
Loading