зеркало из 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->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE) {
|
||||||
if (src->is<InlineTypedObject>()) {
|
if (src->is<InlineTypedObject>()) {
|
||||||
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
|
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
|
||||||
} else if (src->is<UnboxedArrayObject>()) {
|
} else if (src->is<UnboxedArrayObject>()) {
|
||||||
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
|
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
|
||||||
|
} else if (src->is<ArgumentsObject>()) {
|
||||||
|
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
|
||||||
} else {
|
} else {
|
||||||
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
|
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
|
||||||
// to ensure any additional nursery buffers they hold are moved.
|
// to ensure any additional nursery buffers they hold are moved.
|
||||||
MOZ_ASSERT(!(src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE));
|
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() {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче