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:
Jon Coppeard 2019-03-06 16:38:25 +00:00
parent ba8662db5b
commit 297ac5be9c
19 changed files with 72 additions and 48 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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_));

View File

@ -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,

View File

@ -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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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,

View File

@ -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());

View File

@ -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();

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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);