зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1175466 - Allocate arguments objects in the nursery. r=terrence
This commit is contained in:
Родитель
c93d730108
Коммит
38328fd6ab
|
@ -1972,14 +1972,18 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
|
|||
}
|
||||
}
|
||||
|
||||
if (src->is<InlineTypedObject>()) {
|
||||
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
|
||||
} else if (src->is<UnboxedArrayObject>()) {
|
||||
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
|
||||
} else {
|
||||
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
|
||||
// to ensure any additional nursery buffers they hold are moved.
|
||||
MOZ_ASSERT(!(src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE));
|
||||
if (src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE) {
|
||||
if (src->is<InlineTypedObject>()) {
|
||||
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
|
||||
} else if (src->is<UnboxedArrayObject>()) {
|
||||
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
|
||||
} else if (src->is<ArgumentsObject>()) {
|
||||
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
|
||||
} 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;
|
||||
|
|
|
@ -4004,6 +4004,9 @@ JSObject::sizeOfIncludingThisInNursery() const
|
|||
if (!elements.isCopyOnWrite() || elements.ownerObject() == this)
|
||||
size += elements.capacity * sizeof(HeapSlot);
|
||||
}
|
||||
|
||||
if (is<ArgumentsObject>())
|
||||
size += as<ArgumentsObject>().sizeOfData();
|
||||
}
|
||||
|
||||
return size;
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
#include "jit/JitFrames.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -182,31 +185,33 @@ ArgumentsObject::create(JSContext* cx, HandleScript script, HandleFunction calle
|
|||
numDeletedWords * sizeof(size_t) +
|
||||
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);
|
||||
JSObject* base = JSObject::create(cx, FINALIZE_KIND,
|
||||
GetInitialHeap(GenericObject, clasp),
|
||||
shape, group);
|
||||
if (!base) {
|
||||
js_free(data);
|
||||
if (!base)
|
||||
return nullptr;
|
||||
}
|
||||
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->dataBytes = numBytes;
|
||||
data->callee.init(ObjectValue(*callee.get()));
|
||||
data->script = script;
|
||||
|
||||
// Attach the argument object.
|
||||
// Because the argument object was zeroed by pod_calloc(), each Value in
|
||||
// ArgumentsData is DoubleValue(0) and therefore safe for GC tracing.
|
||||
// Zero the argument Values. This sets each value to DoubleValue(0), which
|
||||
// is safe for GC tracing.
|
||||
memset(data->args, 0, numArgs * sizeof(Value));
|
||||
MOZ_ASSERT(DoubleValue(0).asRawBits() == 0x0);
|
||||
MOZ_ASSERT_IF(numArgs > 0, data->args[0].asRawBits() == 0x0);
|
||||
|
||||
obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
|
||||
|
||||
/* Copy [0, numArgs) into data->slots. */
|
||||
|
@ -531,6 +536,7 @@ strictargs_enumerate(JSContext* cx, HandleObject obj)
|
|||
void
|
||||
ArgumentsObject::finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(!IsInsideNursery(obj));
|
||||
fop->free_(reinterpret_cast<void*>(obj->as<ArgumentsObject>().data()));
|
||||
}
|
||||
|
||||
|
@ -544,6 +550,34 @@ ArgumentsObject::trace(JSTracer* trc, JSObject* obj)
|
|||
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
|
||||
* argument values, argument count, and callee function object stored in a
|
||||
|
@ -554,7 +588,9 @@ const Class NormalArgumentsObject::class_ = {
|
|||
"Arguments",
|
||||
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
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 */
|
||||
args_delProperty,
|
||||
nullptr, /* getProperty */
|
||||
|
@ -579,7 +615,9 @@ const Class StrictArgumentsObject::class_ = {
|
|||
"Arguments",
|
||||
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
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 */
|
||||
args_delProperty,
|
||||
nullptr, /* getProperty */
|
||||
|
|
|
@ -33,7 +33,10 @@ struct ArgumentsData
|
|||
* numArgs = Max(numFormalArgs, numActualArgs)
|
||||
* 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
|
||||
|
@ -264,9 +267,13 @@ class ArgumentsObject : public NativeObject
|
|||
size_t sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(data());
|
||||
}
|
||||
size_t sizeOfData() const {
|
||||
return data()->dataBytes;
|
||||
}
|
||||
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src);
|
||||
|
||||
/* For jit use: */
|
||||
static size_t getDataSlotOffset() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче