Bug 912567 - Add post barrier for newTypeObjects r=bhackett

This commit is contained in:
Jon Coppeard 2013-09-24 10:03:57 +01:00
Родитель a9d324a316
Коммит 38b17c9cb2
2 изменённых файлов: 57 добавлений и 4 удалений

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

@ -3487,14 +3487,14 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
/* static */ inline HashNumber
TypeObjectEntry::hash(const Lookup &lookup)
{
return PointerHasher<JSObject *, 3>::hash(lookup.proto.raw()) ^
return PointerHasher<JSObject *, 3>::hash(lookup.hashProto.raw()) ^
PointerHasher<const Class *, 3>::hash(lookup.clasp);
}
/* static */ inline bool
TypeObjectEntry::match(TypeObject *key, const Lookup &lookup)
{
return key->proto == lookup.proto.raw() && key->clasp == lookup.clasp;
return key->proto == lookup.matchProto.raw() && key->clasp == lookup.clasp;
}
#ifdef DEBUG
@ -3531,6 +3531,39 @@ JSObject::setNewTypeUnknown(JSContext *cx, const Class *clasp, HandleObject obj)
return true;
}
#ifdef JSGC_GENERATIONAL
/*
* This class is used to add a post barrier on the newTypeObjects set, as the
* key is calculated from a prototype object which may be moved by generational
* GC.
*/
class NewTypeObjectsSetRef : public BufferableRef
{
TypeObjectSet *set;
TypeObject *typeObject;
JSObject *proto;
public:
NewTypeObjectsSetRef(TypeObjectSet *s, TypeObject *t, JSObject *p)
: set(s), typeObject(t), proto(p) {}
void mark(JSTracer *trc) {
const Class *clasp = typeObject->clasp;
JSObject *prior = proto;
JS_SET_TRACING_LOCATION(trc, (void*)&*prior);
Mark(trc, &proto, "newTypeObjects set prototype");
if (prior == proto)
return;
TypeObjectSet::Ptr p = set->lookup(TypeObjectSet::Lookup(clasp, prior, proto));
JS_ASSERT(p); // newTypeObjects set must still contain original entry.
set->rekeyAs(TypeObjectSet::Lookup(clasp, prior, proto),
TypeObjectSet::Lookup(clasp, proto), typeObject);
}
};
#endif
TypeObject *
ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto_, JSFunction *fun_)
{
@ -3547,6 +3580,8 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto_, JSFunction
uint64_t originalGcNumber = gcNumber();
if (p) {
TypeObject *type = *p;
JS_ASSERT(type->clasp == clasp);
JS_ASSERT(type->proto.get() == proto_.raw());
/*
* If set, the type's newScript indicates the script used to create
@ -3591,6 +3626,13 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto_, JSFunction
if (!added)
return NULL;
#ifdef JSGC_GENERATIONAL
if (proto.isObject() && hasNursery() && nursery().isInside(proto.toObject())) {
asJSContext()->runtime()->gcStoreBuffer.putGeneric(
NewTypeObjectsSetRef(&newTypeObjects, type.get(), proto.toObject()));
}
#endif
if (!typeInferenceEnabled())
return type;

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

@ -1206,9 +1206,20 @@ struct TypeObjectEntry : DefaultHasher<ReadBarriered<TypeObject> >
{
struct Lookup {
const Class *clasp;
TaggedProto proto;
TaggedProto hashProto;
TaggedProto matchProto;
Lookup(const Class *clasp, TaggedProto proto) : clasp(clasp), proto(proto) {}
Lookup(const Class *clasp, TaggedProto proto)
: clasp(clasp), hashProto(proto), matchProto(proto) {}
#ifdef JSGC_GENERATIONAL
/*
* For use by generational post barriers only. Look up an entry whose
* proto has been moved, but was hashed with the original value.
*/
Lookup(const Class *clasp, TaggedProto hashProto, TaggedProto matchProto)
: clasp(clasp), hashProto(hashProto), matchProto(matchProto) {}
#endif
};
static inline HashNumber hash(const Lookup &lookup);