mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 18:26:15 +00:00
Bug 1532376 - Fix places where we don't respect the shouldPretenure flag when creating an object r=jandem
This adds an overload of GetInitialHeap that takes an ObjectGroup* instead of a Class* and also takes into account whether the group's shouldPreTenure flag is set. I moved this to JSObject-inl.h too. I removed the heap parameter in a few places, in particular in NewDenseCopyOnWriteArray which required a bunch of changes elsewhere including the JITs. I left the heap parameter intact for environment objects where we may have reason prefer these objects to be allocated in the tenure heap. It's possible we should just remove all these parameters too and make allocation more uniform. Differential Revision: https://phabricator.services.mozilla.com/D22324
This commit is contained in:
parent
ba8662db5b
commit
297ac5be9c
@ -4064,7 +4064,7 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArray(
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
RootedArrayObject arr(
|
||||
cx, ArrayObject::createArray(
|
||||
cx, allocKind, GetInitialHeap(newKind, &ArrayObject::class_),
|
||||
cx, allocKind, GetInitialHeap(newKind, group),
|
||||
shape, group, length, metadata));
|
||||
if (!arr) {
|
||||
return nullptr;
|
||||
@ -4153,7 +4153,7 @@ ArrayObject* js::NewDenseFullyAllocatedArrayWithTemplate(
|
||||
RootedObjectGroup group(cx, templateObject->group());
|
||||
RootedShape shape(cx, templateObject->as<ArrayObject>().lastProperty());
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, &ArrayObject::class_);
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, group);
|
||||
Rooted<ArrayObject*> arr(
|
||||
cx, ArrayObject::createArray(cx, allocKind, heap, shape, group, length,
|
||||
metadata));
|
||||
@ -4171,10 +4171,11 @@ ArrayObject* js::NewDenseFullyAllocatedArrayWithTemplate(
|
||||
}
|
||||
|
||||
ArrayObject* js::NewDenseCopyOnWriteArray(JSContext* cx,
|
||||
HandleArrayObject templateObject,
|
||||
gc::InitialHeap heap) {
|
||||
HandleArrayObject templateObject) {
|
||||
MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, templateObject->group());
|
||||
|
||||
ArrayObject* arr =
|
||||
ArrayObject::createCopyOnWriteArray(cx, heap, templateObject);
|
||||
if (!arr) {
|
||||
|
@ -79,8 +79,7 @@ extern ArrayObject* NewDenseFullyAllocatedArrayWithTemplate(
|
||||
|
||||
// Create a dense array with the same copy-on-write elements as another object.
|
||||
extern ArrayObject* NewDenseCopyOnWriteArray(JSContext* cx,
|
||||
HandleArrayObject templateObject,
|
||||
gc::InitialHeap heap);
|
||||
HandleArrayObject templateObject);
|
||||
|
||||
extern ArrayObject* NewFullyAllocatedArrayTryUseGroup(
|
||||
JSContext* cx, HandleObjectGroup group, size_t length,
|
||||
|
@ -1553,7 +1553,7 @@ static MOZ_MUST_USE JSObject* ReadableStreamCreateReadResult(
|
||||
NativeObject* obj;
|
||||
JS_TRY_VAR_OR_RETURN_NULL(
|
||||
cx, obj,
|
||||
NativeObject::createWithTemplate(cx, gc::DefaultHeap, templateObject));
|
||||
NativeObject::createWithTemplate(cx, templateObject));
|
||||
|
||||
// Step 5: Perform CreateDataProperty(obj, "value", value).
|
||||
obj->setSlot(Realm::IterResultObjectValueSlot, value);
|
||||
|
@ -2447,10 +2447,9 @@ bool BaselineCompilerCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(Imm32(gc::DefaultHeap));
|
||||
pushArg(ImmGCPtr(obj));
|
||||
|
||||
using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject, gc::InitialHeap);
|
||||
using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject);
|
||||
if (!callVM<Fn, js::NewDenseCopyOnWriteArray>()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -6608,8 +6608,7 @@ void CodeGenerator::visitOutOfLineNewArray(OutOfLineNewArray* ool) {
|
||||
masm.jump(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject,
|
||||
gc::InitialHeap);
|
||||
typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject);
|
||||
static const VMFunction NewArrayCopyOnWriteInfo =
|
||||
FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray,
|
||||
"NewDenseCopyOnWriteArray");
|
||||
@ -6623,7 +6622,7 @@ void CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir) {
|
||||
// If we have a template object, we can inline call object creation.
|
||||
OutOfLineCode* ool =
|
||||
oolCallVM(NewArrayCopyOnWriteInfo, lir,
|
||||
ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
|
||||
ArgList(ImmGCPtr(templateObject)),
|
||||
StoreRegisterTo(objReg));
|
||||
|
||||
TemplateObject templateObj(templateObject);
|
||||
|
@ -1254,12 +1254,10 @@ bool RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const {
|
||||
bool MNewArrayCopyOnWrite::writeRecoverData(CompactBufferWriter& writer) const {
|
||||
MOZ_ASSERT(canRecoverOnBailout());
|
||||
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArrayCopyOnWrite));
|
||||
writer.writeByte(initialHeap());
|
||||
return true;
|
||||
}
|
||||
|
||||
RNewArrayCopyOnWrite::RNewArrayCopyOnWrite(CompactBufferReader& reader) {
|
||||
initialHeap_ = gc::InitialHeap(reader.readByte());
|
||||
}
|
||||
|
||||
bool RNewArrayCopyOnWrite::recover(JSContext* cx,
|
||||
@ -1269,7 +1267,7 @@ bool RNewArrayCopyOnWrite::recover(JSContext* cx,
|
||||
RootedValue result(cx);
|
||||
|
||||
ArrayObject* resultObject =
|
||||
NewDenseCopyOnWriteArray(cx, templateObject, initialHeap_);
|
||||
NewDenseCopyOnWriteArray(cx, templateObject);
|
||||
if (!resultObject) {
|
||||
return false;
|
||||
}
|
||||
|
@ -617,9 +617,6 @@ class RNewArray final : public RInstruction {
|
||||
};
|
||||
|
||||
class RNewArrayCopyOnWrite final : public RInstruction {
|
||||
private:
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
public:
|
||||
RINSTRUCTION_HEADER_NUM_OP_(NewArrayCopyOnWrite, 1)
|
||||
|
||||
|
@ -79,9 +79,11 @@ CallObject* CallObject::create(JSContext* cx, HandleShape shape,
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
kind = gc::GetBackgroundAllocKind(kind);
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, group);
|
||||
|
||||
JSObject* obj;
|
||||
JS_TRY_VAR_OR_RETURN_NULL(
|
||||
cx, obj, NativeObject::create(cx, kind, gc::DefaultHeap, shape, group));
|
||||
cx, obj, NativeObject::create(cx, kind, heap, shape, group));
|
||||
|
||||
return &obj->as<CallObject>();
|
||||
}
|
||||
@ -108,6 +110,10 @@ CallObject* CallObject::createTemplateObject(JSContext* cx, HandleScript script,
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &class_));
|
||||
kind = gc::GetBackgroundAllocKind(kind);
|
||||
|
||||
if (group->shouldPreTenureDontCheckGeneration()) {
|
||||
heap = gc::TenuredHeap;
|
||||
}
|
||||
|
||||
JSObject* obj;
|
||||
JS_TRY_VAR_OR_RETURN_NULL(cx, obj,
|
||||
NativeObject::create(cx, kind, heap, shape, group));
|
||||
@ -887,6 +893,10 @@ LexicalEnvironmentObject* LexicalEnvironmentObject::createTemplateObject(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (group->shouldPreTenureDontCheckGeneration()) {
|
||||
heap = gc::TenuredHeap;
|
||||
}
|
||||
|
||||
gc::AllocKind allocKind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
MOZ_ASSERT(
|
||||
CanBeFinalizedInBackground(allocKind, &LexicalEnvironmentObject::class_));
|
||||
|
@ -5288,7 +5288,7 @@ ArrayObject* js::NewArrayCopyOnWriteOperation(JSContext* cx,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return NewDenseCopyOnWriteArray(cx, baseobj, gc::DefaultHeap);
|
||||
return NewDenseCopyOnWriteArray(cx, baseobj);
|
||||
}
|
||||
|
||||
void js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
|
||||
|
@ -619,7 +619,7 @@ static PropertyIteratorObject* NewPropertyIteratorObject(JSContext* cx) {
|
||||
JS_TRY_VAR_OR_RETURN_NULL(
|
||||
cx, obj,
|
||||
NativeObject::create(cx, ITERATOR_FINALIZE_KIND,
|
||||
GetInitialHeap(GenericObject, clasp), shape, group));
|
||||
GetInitialHeap(GenericObject, group), shape, group));
|
||||
|
||||
PropertyIteratorObject* res = &obj->as<PropertyIteratorObject>();
|
||||
|
||||
@ -996,7 +996,7 @@ JSObject* js::CreateIterResultObject(JSContext* cx, HandleValue value,
|
||||
NativeObject* resultObj;
|
||||
JS_TRY_VAR_OR_RETURN_NULL(
|
||||
cx, resultObj,
|
||||
NativeObject::createWithTemplate(cx, gc::DefaultHeap, templateObject));
|
||||
NativeObject::createWithTemplate(cx, templateObject));
|
||||
|
||||
// Step 3.
|
||||
resultObj->setSlot(Realm::IterResultObjectValueSlot, value);
|
||||
|
@ -399,6 +399,32 @@ inline bool IsInternalFunctionObject(JSObject& funobj) {
|
||||
return fun.isInterpreted() && !fun.environment();
|
||||
}
|
||||
|
||||
inline gc::InitialHeap GetInitialHeap(NewObjectKind newKind,
|
||||
const Class* clasp) {
|
||||
if (newKind == NurseryAllocatedProxy) {
|
||||
MOZ_ASSERT(clasp->isProxy());
|
||||
MOZ_ASSERT(clasp->hasFinalize());
|
||||
MOZ_ASSERT(!CanNurseryAllocateFinalizedClass(clasp));
|
||||
return gc::DefaultHeap;
|
||||
}
|
||||
if (newKind != GenericObject) {
|
||||
return gc::TenuredHeap;
|
||||
}
|
||||
if (clasp->hasFinalize() && !CanNurseryAllocateFinalizedClass(clasp)) {
|
||||
return gc::TenuredHeap;
|
||||
}
|
||||
return gc::DefaultHeap;
|
||||
}
|
||||
|
||||
inline gc::InitialHeap GetInitialHeap(NewObjectKind newKind,
|
||||
ObjectGroup* group) {
|
||||
if (group->shouldPreTenureDontCheckGeneration()) {
|
||||
return gc::TenuredHeap;
|
||||
}
|
||||
|
||||
return GetInitialHeap(newKind, group->clasp());
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an object with the specified prototype. If parent is null, it will
|
||||
* default to the prototype's global if the prototype is non-null.
|
||||
|
@ -792,7 +792,7 @@ static inline JSObject* NewObject(JSContext* cx, HandleObjectGroup group,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, group);
|
||||
|
||||
JSObject* obj;
|
||||
if (clasp->isJSFunction()) {
|
||||
@ -975,7 +975,7 @@ JSObject* js::NewObjectWithGroupCommon(JSContext* cx, HandleObjectGroup group,
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGroup(group, allocKind, &entry)) {
|
||||
JSObject* obj = cache.newObjectFromHit(
|
||||
cx, entry, GetInitialHeap(newKind, group->clasp()));
|
||||
cx, entry, GetInitialHeap(newKind, group));
|
||||
if (obj) {
|
||||
return obj;
|
||||
}
|
||||
|
@ -802,23 +802,6 @@ using ClassInitializerOp = JSObject* (*)(JSContext* cx,
|
||||
|
||||
namespace js {
|
||||
|
||||
inline gc::InitialHeap GetInitialHeap(NewObjectKind newKind,
|
||||
const Class* clasp) {
|
||||
if (newKind == NurseryAllocatedProxy) {
|
||||
MOZ_ASSERT(clasp->isProxy());
|
||||
MOZ_ASSERT(clasp->hasFinalize());
|
||||
MOZ_ASSERT(!CanNurseryAllocateFinalizedClass(clasp));
|
||||
return gc::DefaultHeap;
|
||||
}
|
||||
if (newKind != GenericObject) {
|
||||
return gc::TenuredHeap;
|
||||
}
|
||||
if (clasp->hasFinalize() && !CanNurseryAllocateFinalizedClass(clasp)) {
|
||||
return gc::TenuredHeap;
|
||||
}
|
||||
return gc::DefaultHeap;
|
||||
}
|
||||
|
||||
bool NewObjectWithTaggedProtoIsCachable(JSContext* cx,
|
||||
Handle<TaggedProto> proto,
|
||||
NewObjectKind newKind,
|
||||
|
@ -522,9 +522,11 @@ inline bool NativeObject::isInWholeCellBuffer() const {
|
||||
}
|
||||
|
||||
/* static */ inline JS::Result<NativeObject*, JS::OOM&>
|
||||
NativeObject::createWithTemplate(JSContext* cx, js::gc::InitialHeap heap,
|
||||
HandleObject templateObject) {
|
||||
NativeObject::createWithTemplate(JSContext* cx, HandleObject templateObject) {
|
||||
RootedObjectGroup group(cx, templateObject->group());
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, group);
|
||||
|
||||
RootedShape shape(cx, templateObject->as<NativeObject>().lastProperty());
|
||||
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
|
@ -565,7 +565,7 @@ class NativeObject : public ShapedObject {
|
||||
js::HandleShape shape, js::HandleObjectGroup group);
|
||||
|
||||
static inline JS::Result<NativeObject*, JS::OOM&> createWithTemplate(
|
||||
JSContext* cx, js::gc::InitialHeap heap, HandleObject templateObject);
|
||||
JSContext* cx, HandleObject templateObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void enableShapeConsistencyChecks();
|
||||
|
@ -54,8 +54,13 @@ inline bool ObjectGroup::unknownProperties(const AutoSweepObjectGroup& sweep) {
|
||||
}
|
||||
|
||||
inline bool ObjectGroup::shouldPreTenure(const AutoSweepObjectGroup& sweep) {
|
||||
return hasAnyFlags(sweep, OBJECT_FLAG_PRE_TENURE) &&
|
||||
!unknownProperties(sweep);
|
||||
MOZ_ASSERT(sweep.group() == this);
|
||||
return shouldPreTenureDontCheckGeneration();
|
||||
}
|
||||
|
||||
inline bool ObjectGroup::shouldPreTenureDontCheckGeneration() {
|
||||
return hasAnyFlagsDontCheckGeneration(OBJECT_FLAG_PRE_TENURE) &&
|
||||
!unknownPropertiesDontCheckGeneration();
|
||||
}
|
||||
|
||||
inline bool ObjectGroup::canPreTenure(const AutoSweepObjectGroup& sweep) {
|
||||
|
@ -404,6 +404,10 @@ class ObjectGroup : public gc::TenuredCell {
|
||||
inline bool hasAllFlags(const AutoSweepObjectGroup& sweep,
|
||||
ObjectGroupFlags flags);
|
||||
|
||||
bool hasAnyFlagsDontCheckGeneration(ObjectGroupFlags flags) {
|
||||
MOZ_ASSERT((flags & OBJECT_FLAG_DYNAMIC_MASK) == flags);
|
||||
return !!(this->flagsDontCheckGeneration() & flags);
|
||||
}
|
||||
bool hasAllFlagsDontCheckGeneration(ObjectGroupFlags flags) {
|
||||
MOZ_ASSERT((flags & OBJECT_FLAG_DYNAMIC_MASK) == flags);
|
||||
return (this->flagsDontCheckGeneration() & flags) == flags;
|
||||
@ -418,6 +422,7 @@ class ObjectGroup : public gc::TenuredCell {
|
||||
}
|
||||
|
||||
inline bool shouldPreTenure(const AutoSweepObjectGroup& sweep);
|
||||
inline bool shouldPreTenureDontCheckGeneration();
|
||||
|
||||
gc::InitialHeap initialHeap(CompilerConstraintList* constraints);
|
||||
|
||||
|
@ -184,7 +184,7 @@ void ProxyObject::nuke() {
|
||||
realm->newProxyCache.add(group, shape);
|
||||
}
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, group);
|
||||
debugCheckNewObject(group, shape, allocKind, heap);
|
||||
|
||||
JSObject* obj = js::Allocate<JSObject>(cx, allocKind, /* nDynamicSlots = */ 0,
|
||||
|
@ -875,7 +875,7 @@ UnboxedPlainObject* UnboxedPlainObject::create(JSContext* cx,
|
||||
AutoSweepObjectGroup sweep(group);
|
||||
allocKind = group->unboxedLayout(sweep).getAllocKind();
|
||||
}
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, &class_);
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, group);
|
||||
|
||||
MOZ_ASSERT(newKind != SingletonObject);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user