Bug 1175466 - Allocate arguments objects in the nursery. r=terrence

This commit is contained in:
Jan de Mooij 2015-06-20 21:30:12 -07:00
Родитель c93d730108
Коммит 38328fd6ab
4 изменённых файлов: 75 добавлений и 23 удалений

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

@ -1972,14 +1972,18 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
} }
} }
if (src->is<InlineTypedObject>()) { if (src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE) {
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src); if (src->is<InlineTypedObject>()) {
} else if (src->is<UnboxedArrayObject>()) { InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind); } else if (src->is<UnboxedArrayObject>()) {
} else { tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above } else if (src->is<ArgumentsObject>()) {
// to ensure any additional nursery buffers they hold are moved. tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
MOZ_ASSERT(!(src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE)); } else {
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
// to ensure any additional nursery buffers they hold are moved.
MOZ_CRASH("Unhandled JSCLASS_SKIP_NURSERY_FINALIZE Class");
}
} }
return tenuredSize; return tenuredSize;

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

@ -4004,6 +4004,9 @@ JSObject::sizeOfIncludingThisInNursery() const
if (!elements.isCopyOnWrite() || elements.ownerObject() == this) if (!elements.isCopyOnWrite() || elements.ownerObject() == this)
size += elements.capacity * sizeof(HeapSlot); size += elements.capacity * sizeof(HeapSlot);
} }
if (is<ArgumentsObject>())
size += as<ArgumentsObject>().sizeOfData();
} }
return size; return size;

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

@ -6,12 +6,15 @@
#include "vm/ArgumentsObject-inl.h" #include "vm/ArgumentsObject-inl.h"
#include "mozilla/PodOperations.h"
#include "jit/JitFrames.h" #include "jit/JitFrames.h"
#include "vm/GlobalObject.h" #include "vm/GlobalObject.h"
#include "vm/Stack.h" #include "vm/Stack.h"
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "gc/Nursery-inl.h"
#include "vm/Stack-inl.h" #include "vm/Stack-inl.h"
using namespace js; using namespace js;
@ -182,31 +185,33 @@ ArgumentsObject::create(JSContext* cx, HandleScript script, HandleFunction calle
numDeletedWords * sizeof(size_t) + numDeletedWords * sizeof(size_t) +
numArgs * sizeof(Value); numArgs * sizeof(Value);
// Allocate zeroed memory to make the object GC-safe for early attachment.
ArgumentsData* data = reinterpret_cast<ArgumentsData*>(
cx->zone()->pod_calloc<uint8_t>(numBytes));
if (!data)
return nullptr;
Rooted<ArgumentsObject*> obj(cx); Rooted<ArgumentsObject*> obj(cx);
JSObject* base = JSObject::create(cx, FINALIZE_KIND, JSObject* base = JSObject::create(cx, FINALIZE_KIND,
GetInitialHeap(GenericObject, clasp), GetInitialHeap(GenericObject, clasp),
shape, group); shape, group);
if (!base) { if (!base)
js_free(data);
return nullptr; return nullptr;
}
obj = &base->as<ArgumentsObject>(); obj = &base->as<ArgumentsObject>();
ArgumentsData* data =
reinterpret_cast<ArgumentsData*>(AllocateObjectBuffer<uint8_t>(cx, obj, numBytes));
if (!data) {
// Make the object safe for GC.
obj->initFixedSlot(DATA_SLOT, PrivateValue(nullptr));
return nullptr;
}
data->numArgs = numArgs; data->numArgs = numArgs;
data->dataBytes = numBytes;
data->callee.init(ObjectValue(*callee.get())); data->callee.init(ObjectValue(*callee.get()));
data->script = script; data->script = script;
// Attach the argument object. // Zero the argument Values. This sets each value to DoubleValue(0), which
// Because the argument object was zeroed by pod_calloc(), each Value in // is safe for GC tracing.
// ArgumentsData is DoubleValue(0) and therefore safe for GC tracing. memset(data->args, 0, numArgs * sizeof(Value));
MOZ_ASSERT(DoubleValue(0).asRawBits() == 0x0); MOZ_ASSERT(DoubleValue(0).asRawBits() == 0x0);
MOZ_ASSERT_IF(numArgs > 0, data->args[0].asRawBits() == 0x0); MOZ_ASSERT_IF(numArgs > 0, data->args[0].asRawBits() == 0x0);
obj->initFixedSlot(DATA_SLOT, PrivateValue(data)); obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
/* Copy [0, numArgs) into data->slots. */ /* Copy [0, numArgs) into data->slots. */
@ -531,6 +536,7 @@ strictargs_enumerate(JSContext* cx, HandleObject obj)
void void
ArgumentsObject::finalize(FreeOp* fop, JSObject* obj) ArgumentsObject::finalize(FreeOp* fop, JSObject* obj)
{ {
MOZ_ASSERT(!IsInsideNursery(obj));
fop->free_(reinterpret_cast<void*>(obj->as<ArgumentsObject>().data())); fop->free_(reinterpret_cast<void*>(obj->as<ArgumentsObject>().data()));
} }
@ -544,6 +550,34 @@ ArgumentsObject::trace(JSTracer* trc, JSObject* obj)
TraceManuallyBarrieredEdge(trc, &data->script, "script"); TraceManuallyBarrieredEdge(trc, &data->script, "script");
} }
/* static */ size_t
ArgumentsObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src)
{
ArgumentsObject* ndst = &dst->as<ArgumentsObject>();
ArgumentsObject* nsrc = &src->as<ArgumentsObject>();
MOZ_ASSERT(ndst->data() == nsrc->data());
Nursery& nursery = trc->runtime()->gc.nursery;
if (!nursery.isInside(nsrc->data())) {
nursery.removeMallocedBuffer(nsrc->data());
return 0;
}
uint32_t nbytes = nsrc->data()->dataBytes;
uint8_t* data = nsrc->zone()->pod_malloc<uint8_t>(nbytes);
if (!data)
CrashAtUnhandlableOOM("Failed to allocate ArgumentsObject data while tenuring.");
ndst->initFixedSlot(DATA_SLOT, PrivateValue(data));
mozilla::PodCopy(data, reinterpret_cast<uint8_t*>(nsrc->data()), nbytes);
ArgumentsData* dstData = ndst->data();
dstData->deletedBits = reinterpret_cast<size_t*>(dstData->args + dstData->numArgs);
return nbytes;
}
/* /*
* The classes below collaborate to lazily reflect and synchronize actual * The classes below collaborate to lazily reflect and synchronize actual
* argument values, argument count, and callee function object stored in a * argument values, argument count, and callee function object stored in a
@ -554,7 +588,9 @@ const Class NormalArgumentsObject::class_ = {
"Arguments", "Arguments",
JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_IMPLEMENTS_BARRIERS |
JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE, JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
JSCLASS_SKIP_NURSERY_FINALIZE |
JSCLASS_BACKGROUND_FINALIZE,
nullptr, /* addProperty */ nullptr, /* addProperty */
args_delProperty, args_delProperty,
nullptr, /* getProperty */ nullptr, /* getProperty */
@ -579,7 +615,9 @@ const Class StrictArgumentsObject::class_ = {
"Arguments", "Arguments",
JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_IMPLEMENTS_BARRIERS |
JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE, JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
JSCLASS_SKIP_NURSERY_FINALIZE |
JSCLASS_BACKGROUND_FINALIZE,
nullptr, /* addProperty */ nullptr, /* addProperty */
args_delProperty, args_delProperty,
nullptr, /* getProperty */ nullptr, /* getProperty */

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

@ -33,7 +33,10 @@ struct ArgumentsData
* numArgs = Max(numFormalArgs, numActualArgs) * numArgs = Max(numFormalArgs, numActualArgs)
* The array 'args' has numArgs elements. * The array 'args' has numArgs elements.
*/ */
unsigned numArgs; uint32_t numArgs;
/* Size of ArgumentsData and data allocated after it. */
uint32_t dataBytes;
/* /*
* arguments.callee, or MagicValue(JS_OVERWRITTEN_CALLEE) if * arguments.callee, or MagicValue(JS_OVERWRITTEN_CALLEE) if
@ -264,9 +267,13 @@ class ArgumentsObject : public NativeObject
size_t sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const { size_t sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const {
return mallocSizeOf(data()); return mallocSizeOf(data());
} }
size_t sizeOfData() const {
return data()->dataBytes;
}
static void finalize(FreeOp* fop, JSObject* obj); static void finalize(FreeOp* fop, JSObject* obj);
static void trace(JSTracer* trc, JSObject* obj); static void trace(JSTracer* trc, JSObject* obj);
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src);
/* For jit use: */ /* For jit use: */
static size_t getDataSlotOffset() { static size_t getDataSlotOffset() {