Bug 1396613 - Replace special cases with use of objectMoved hook when tenuring r=sfink

This commit is contained in:
Jon Coppeard 2017-09-19 12:31:30 +01:00
parent 1077972535
commit 2a663c4c5a
10 changed files with 87 additions and 70 deletions

View File

@ -2126,9 +2126,12 @@ InlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
typedObj.typeDescr().traceInstances(trc, typedObj.inlineTypedMem(), 1);
}
/* static */ void
InlineTypedObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src)
/* static */ size_t
InlineTypedObject::obj_moved(JSObject* dst, JSObject* src)
{
if (!IsInsideNursery(src))
return 0;
// Inline typed object element arrays can be preserved on the stack by Ion
// and need forwarding pointers created during a minor GC. We can't do this
// in the trace hook because we don't have any stale data to determine
@ -2140,9 +2143,12 @@ InlineTypedObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObje
// but they will not set any direct forwarding pointers.
uint8_t* oldData = reinterpret_cast<uint8_t*>(src) + offsetOfDataStart();
uint8_t* newData = dst->as<InlineTypedObject>().inlineTypedMem();
dst->zone()->group()->nursery().maybeSetForwardingPointer(trc, oldData, newData,
descr.size() >= sizeof(uintptr_t));
auto& nursery = dst->zone()->group()->nursery();
bool direct = descr.size() >= sizeof(uintptr_t);
nursery.setForwardingPointerWhileTenuring(oldData, newData, direct);
}
return 0;
}
ArrayBufferObject*
@ -2219,7 +2225,7 @@ const ObjectOps TypedObject::objectOps_ = {
nullptr, /* thisValue */
};
#define DEFINE_TYPEDOBJ_CLASS(Name, Trace, flag) \
#define DEFINE_TYPEDOBJ_CLASS(Name, Trace, Moved, flag) \
static const ClassOps Name##ClassOps = { \
nullptr, /* addProperty */ \
nullptr, /* delProperty */ \
@ -2233,20 +2239,34 @@ const ObjectOps TypedObject::objectOps_ = {
nullptr, /* construct */ \
Trace, \
}; \
static const ClassExtension Name##ClassExt = { \
nullptr, /* weakmapKeyDelegateOp */ \
Moved /* objectMovedOp */ \
}; \
const Class Name::class_ = { \
# Name, \
Class::NON_NATIVE | flag, \
&Name##ClassOps, \
JS_NULL_CLASS_SPEC, \
JS_NULL_CLASS_EXT, \
&Name##ClassExt, \
&TypedObject::objectOps_ \
}
DEFINE_TYPEDOBJ_CLASS(OutlineTransparentTypedObject, OutlineTypedObject::obj_trace, 0);
DEFINE_TYPEDOBJ_CLASS(OutlineOpaqueTypedObject, OutlineTypedObject::obj_trace, 0);
DEFINE_TYPEDOBJ_CLASS(InlineTransparentTypedObject, InlineTypedObject::obj_trace,
DEFINE_TYPEDOBJ_CLASS(OutlineTransparentTypedObject,
OutlineTypedObject::obj_trace,
nullptr,
0);
DEFINE_TYPEDOBJ_CLASS(OutlineOpaqueTypedObject,
OutlineTypedObject::obj_trace,
nullptr,
0);
DEFINE_TYPEDOBJ_CLASS(InlineTransparentTypedObject,
InlineTypedObject::obj_trace,
InlineTypedObject::obj_moved,
JSCLASS_DELAY_METADATA_BUILDER);
DEFINE_TYPEDOBJ_CLASS(InlineOpaqueTypedObject, InlineTypedObject::obj_trace,
DEFINE_TYPEDOBJ_CLASS(InlineOpaqueTypedObject,
InlineTypedObject::obj_trace,
InlineTypedObject::obj_moved,
JSCLASS_DELAY_METADATA_BUILDER);
static int32_t

View File

@ -723,7 +723,7 @@ class InlineTypedObject : public TypedObject
}
static void obj_trace(JSTracer* trace, JSObject* object);
static void objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src);
static size_t obj_moved(JSObject* dst, JSObject* src);
static size_t offsetOfDataStart() {
return offsetof(InlineTypedObject, data_);

View File

@ -2976,15 +2976,10 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
// shape list. This is updated in Nursery::sweepDictionaryModeObjects().
}
if (src->is<InlineTypedObject>()) {
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<TypedArrayObject>()) {
tenuredSize += TypedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
} else if (src->is<UnboxedArrayObject>()) {
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
} else if (src->is<ArgumentsObject>()) {
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<ProxyObject>()) {
if (src->is<ProxyObject>()) {
// TODO: Push this logic into proxy_ObjectMoved and make all proxies use
// this.
// Objects in the nursery are never swapped so the proxy must have an
// inline ProxyValueArray.
MOZ_ASSERT(src->as<ProxyObject>().usingInlineValueArray());

View File

@ -217,7 +217,12 @@ class Nursery
void forwardBufferPointer(HeapSlot** pSlotsElems);
void maybeSetForwardingPointer(JSTracer* trc, void* oldData, void* newData, bool direct) {
if (trc->isTenuringTracer() && isInside(oldData))
if (trc->isTenuringTracer())
setForwardingPointerWhileTenuring(oldData, newData, direct);
}
void setForwardingPointerWhileTenuring(void* oldData, void* newData, bool direct) {
if (isInside(oldData))
setForwardingPointer(oldData, newData, direct);
}

View File

@ -855,12 +855,15 @@ ArgumentsObject::trace(JSTracer* trc, JSObject* obj)
}
/* static */ size_t
ArgumentsObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src)
ArgumentsObject::objectMoved(JSObject* dst, JSObject* src)
{
ArgumentsObject* ndst = &dst->as<ArgumentsObject>();
ArgumentsObject* nsrc = &src->as<ArgumentsObject>();
const ArgumentsObject* nsrc = &src->as<ArgumentsObject>();
MOZ_ASSERT(ndst->data() == nsrc->data());
if (!IsInsideNursery(src))
return 0;
Nursery& nursery = dst->zone()->group()->nursery();
size_t nbytesTotal = 0;
@ -917,6 +920,11 @@ const ClassOps MappedArgumentsObject::classOps_ = {
ArgumentsObject::trace
};
const js::ClassExtension MappedArgumentsObject::classExt_ = {
nullptr, /* weakmapKeyDelegateOp */
ArgumentsObject::objectMoved /* objectMovedOp */
};
const ObjectOps MappedArgumentsObject::objectOps_ = {
nullptr, /* lookupProperty */
MappedArgumentsObject::obj_defineProperty
@ -931,7 +939,7 @@ const Class MappedArgumentsObject::class_ = {
JSCLASS_BACKGROUND_FINALIZE,
&MappedArgumentsObject::classOps_,
nullptr,
nullptr,
&MappedArgumentsObject::classExt_,
&MappedArgumentsObject::objectOps_
};
@ -953,6 +961,11 @@ const ClassOps UnmappedArgumentsObject::classOps_ = {
ArgumentsObject::trace
};
const js::ClassExtension UnmappedArgumentsObject::classExt_ = {
nullptr, /* weakmapKeyDelegateOp */
ArgumentsObject::objectMoved /* objectMovedOp */
};
const Class UnmappedArgumentsObject::class_ = {
"Arguments",
JSCLASS_DELAY_METADATA_BUILDER |
@ -960,5 +973,7 @@ const Class UnmappedArgumentsObject::class_ = {
JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
JSCLASS_SKIP_NURSERY_FINALIZE |
JSCLASS_BACKGROUND_FINALIZE,
&UnmappedArgumentsObject::classOps_
&UnmappedArgumentsObject::classOps_,
nullptr,
&UnmappedArgumentsObject::classExt_
};

View File

@ -361,7 +361,7 @@ class ArgumentsObject : public NativeObject
static void finalize(FreeOp* fop, JSObject* obj);
static void trace(JSTracer* trc, JSObject* obj);
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src);
static size_t objectMoved(JSObject* dst, JSObject* src);
/* For jit use: */
static size_t getDataSlotOffset() {
@ -399,6 +399,7 @@ class ArgumentsObject : public NativeObject
class MappedArgumentsObject : public ArgumentsObject
{
static const ClassOps classOps_;
static const ClassExtension classExt_;
static const ObjectOps objectOps_;
public:
@ -428,6 +429,7 @@ class MappedArgumentsObject : public ArgumentsObject
class UnmappedArgumentsObject : public ArgumentsObject
{
static const ClassOps classOps_;
static const ClassExtension classExt_;
public:
static const Class class_;

View File

@ -184,25 +184,7 @@ TypedArrayObject::finalize(FreeOp* fop, JSObject* obj)
TypedArrayObject::objectMoved(JSObject* obj, JSObject* old)
{
TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
// Typed arrays with a buffer object do not need an update.
if (oldObj->hasBuffer())
return 0;
// Update the data slot pointer if it points to the old JSObject.
if (oldObj->hasInlineElements())
newObj->setInlineElements();
return 0;
}
/* static */ size_t
TypedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const JSObject* old,
gc::AllocKind newAllocKind)
{
TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
MOZ_ASSERT(newObj->elementsRaw() == oldObj->elementsRaw());
MOZ_ASSERT(obj->isTenured());
@ -210,6 +192,14 @@ TypedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const J
if (oldObj->hasBuffer())
return 0;
if (!IsInsideNursery(old)) {
// Update the data slot pointer if it points to the old JSObject.
if (oldObj->hasInlineElements())
newObj->setInlineElements();
return 0;
}
Nursery& nursery = obj->zone()->group()->nursery();
void* buf = oldObj->elements();
@ -236,6 +226,7 @@ JS_FOR_EACH_TYPED_ARRAY(OBJECT_MOVED_TYPED_ARRAY)
size_t headerSize = dataOffset() + sizeof(HeapSlot);
// See AllocKindForLazyBuffer.
AllocKind newAllocKind = obj->asTenured().getAllocKind();
MOZ_ASSERT_IF(nbytes == 0, headerSize + sizeof(uint8_t) <= GetGCKindBytes(newAllocKind));
if (headerSize + nbytes <= GetGCKindBytes(newAllocKind)) {
@ -262,8 +253,8 @@ JS_FOR_EACH_TYPED_ARRAY(OBJECT_MOVED_TYPED_ARRAY)
// Set a forwarding pointer for the element buffers in case they were
// preserved on the stack by Ion.
nursery.maybeSetForwardingPointer(trc, oldObj->elements(), newObj->elements(),
/* direct = */nbytes >= sizeof(uintptr_t));
nursery.setForwardingPointerWhileTenuring(oldObj->elements(), newObj->elements(),
/* direct = */nbytes >= sizeof(uintptr_t));
return newObj->hasInlineElements() ? 0 : nbytes;
}

View File

@ -274,8 +274,6 @@ class TypedArrayObject : public NativeObject
static void trace(JSTracer* trc, JSObject* obj);
static void finalize(FreeOp* fop, JSObject* obj);
static size_t objectMoved(JSObject* obj, JSObject* old);
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const JSObject* old,
gc::AllocKind allocKind);
/* Initialization bits */

View File

@ -1203,19 +1203,6 @@ UnboxedArrayObject::trace(JSTracer* trc, JSObject* obj)
}
}
/* static */ size_t
UnboxedArrayObject::objectMoved(JSObject* obj, JSObject* old)
{
UnboxedArrayObject& dst = obj->as<UnboxedArrayObject>();
const UnboxedArrayObject& src = old->as<UnboxedArrayObject>();
// Fix up possible inline data pointer.
if (src.hasInlineElements())
dst.setInlineElements();
return 0;
}
/* static */ void
UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
{
@ -1225,15 +1212,21 @@ UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
}
/* static */ size_t
UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
gc::AllocKind allocKind)
UnboxedArrayObject::objectMoved(JSObject* dst, JSObject* src)
{
UnboxedArrayObject* ndst = &dst->as<UnboxedArrayObject>();
UnboxedArrayObject* nsrc = &src->as<UnboxedArrayObject>();
MOZ_ASSERT(ndst->elements() == nsrc->elements());
Nursery& nursery = dst->zone()->group()->nursery();
if (!IsInsideNursery(src)) {
// Fix up possible inline data pointer.
if (nsrc->hasInlineElements())
ndst->setInlineElements();
return 0;
}
Nursery& nursery = dst->zone()->group()->nursery();
if (!nursery.isInside(nsrc->elements())) {
nursery.removeMallocedBuffer(nsrc->elements());
return 0;
@ -1243,7 +1236,8 @@ UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObj
// possible, the nursery will have picked an allocation size that is large
// enough.
size_t nbytes = nsrc->capacity() * nsrc->elementSize();
if (offsetOfInlineElements() + nbytes <= GetGCKindBytes(allocKind)) {
gc::AllocKind allocKind = dst->asTenured().getAllocKind();
if (offsetOfInlineElements() + nbytes <= gc::GetGCKindBytes(allocKind)) {
ndst->setInlineElements();
} else {
MOZ_ASSERT(allocKind == gc::AllocKind::OBJECT0);
@ -1260,7 +1254,7 @@ UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObj
// Set a forwarding pointer for the element buffers in case they were
// preserved on the stack by Ion.
bool direct = nsrc->capacity() * nsrc->elementSize() >= sizeof(uintptr_t);
nursery.maybeSetForwardingPointer(trc, nsrc->elements(), ndst->elements(), direct);
nursery.setForwardingPointerWhileTenuring(nsrc->elements(), ndst->elements(), direct);
return ndst->hasInlineElements() ? 0 : nbytes;
}

View File

@ -446,9 +446,6 @@ class UnboxedArrayObject : public UnboxedObject
static size_t objectMoved(JSObject* obj, JSObject* old);
static void finalize(FreeOp* fop, JSObject* obj);
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
gc::AllocKind allocKind);
uint8_t* elements() {
return elements_;
}