Backed out 2 changesets (bug 1532376) for causing build bustages in the merge from central to autoland CLOSED TREE
authorCiure Andrei <aciure@mozilla.com>
Fri, 22 Mar 2019 19:25:52 +0200
changeset 465733 bbb45318486338a306aa31841e02f64d47d2d822
parent 465732 f23caf168c32b31b5bae01c15bf958dca5571a01
child 465734 6ba48873ecaeddaad9f6c58f7e3d19be4208ffed
push id35746
push usershindli@mozilla.com
push dateSat, 23 Mar 2019 09:46:24 +0000
treeherdermozilla-central@02b7484f316b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1532376
milestone68.0a1
backs out49304ded1ad6138ad30becc0fbd911129e8d5b26
6af6ae0901ccc397e9e41935a72a66408fc6f593
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 2 changesets (bug 1532376) for causing build bustages in the merge from central to autoland CLOSED TREE Backed out changeset 49304ded1ad6 (bug 1532376) Backed out changeset 6af6ae0901cc (bug 1532376)
js/src/builtin/Array.cpp
js/src/builtin/Array.h
js/src/builtin/Stream.cpp
js/src/jit-test/tests/gc/bug-1532376.js
js/src/jit/BaselineCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/Recover.cpp
js/src/jit/Recover.h
js/src/vm/ArrayObject-inl.h
js/src/vm/EnvironmentObject.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Iteration.cpp
js/src/vm/JSObject-inl.h
js/src/vm/JSObject.cpp
js/src/vm/JSObject.h
js/src/vm/NativeObject-inl.h
js/src/vm/NativeObject.h
js/src/vm/ObjectGroup-inl.h
js/src/vm/ObjectGroup.h
js/src/vm/ProxyObject.cpp
js/src/vm/UnboxedObject.cpp
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -4072,19 +4072,20 @@ static MOZ_ALWAYS_INLINE ArrayObject* Ne
   RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayObject::class_,
                                                     TaggedProto(proto),
                                                     gc::AllocKind::OBJECT0));
   if (!shape) {
     return nullptr;
   }
 
   AutoSetNewObjectMetadata metadata(cx);
-  RootedArrayObject arr(cx, ArrayObject::createArray(
-                                cx, allocKind, GetInitialHeap(newKind, group),
-                                shape, group, length, metadata));
+  RootedArrayObject arr(
+      cx, ArrayObject::createArray(
+              cx, allocKind, GetInitialHeap(newKind, &ArrayObject::class_),
+              shape, group, length, metadata));
   if (!arr) {
     return nullptr;
   }
 
   if (shape->isEmptyShape()) {
     if (!AddLengthProperty(cx, arr)) {
       return nullptr;
     }
@@ -4162,17 +4163,17 @@ ArrayObject* js::NewDenseFullyAllocatedA
   AutoSetNewObjectMetadata metadata(cx);
   gc::AllocKind allocKind = GuessArrayGCKind(length);
   MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
   allocKind = GetBackgroundAllocKind(allocKind);
 
   RootedObjectGroup group(cx, templateObject->group());
   RootedShape shape(cx, templateObject->as<ArrayObject>().lastProperty());
 
-  gc::InitialHeap heap = GetInitialHeap(GenericObject, group);
+  gc::InitialHeap heap = GetInitialHeap(GenericObject, &ArrayObject::class_);
   Rooted<ArrayObject*> arr(
       cx, ArrayObject::createArray(cx, allocKind, heap, shape, group, length,
                                    metadata));
   if (!arr) {
     return nullptr;
   }
 
   if (!EnsureNewArrayElements(cx, arr, length)) {
@@ -4180,21 +4181,20 @@ ArrayObject* js::NewDenseFullyAllocatedA
   }
 
   probes::CreateObject(cx, arr);
 
   return arr;
 }
 
 ArrayObject* js::NewDenseCopyOnWriteArray(JSContext* cx,
-                                          HandleArrayObject templateObject) {
+                                          HandleArrayObject templateObject,
+                                          gc::InitialHeap heap) {
   MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
 
-  gc::InitialHeap heap = GetInitialHeap(GenericObject, templateObject->group());
-
   ArrayObject* arr =
       ArrayObject::createCopyOnWriteArray(cx, heap, templateObject);
   if (!arr) {
     return nullptr;
   }
 
   probes::CreateObject(cx, arr);
   return arr;
--- a/js/src/builtin/Array.h
+++ b/js/src/builtin/Array.h
@@ -74,17 +74,18 @@ extern ArrayObject* NewDenseCopiedArray(
                                         NewObjectKind newKind = GenericObject);
 
 // Create a dense array based on templateObject with the given length.
 extern ArrayObject* NewDenseFullyAllocatedArrayWithTemplate(
     JSContext* cx, uint32_t length, JSObject* templateObject);
 
 // Create a dense array with the same copy-on-write elements as another object.
 extern ArrayObject* NewDenseCopyOnWriteArray(JSContext* cx,
-                                             HandleArrayObject templateObject);
+                                             HandleArrayObject templateObject,
+                                             gc::InitialHeap heap);
 
 extern ArrayObject* NewFullyAllocatedArrayTryUseGroup(
     JSContext* cx, HandleObjectGroup group, size_t length,
     NewObjectKind newKind = GenericObject);
 
 extern ArrayObject* NewPartlyAllocatedArrayTryUseGroup(JSContext* cx,
                                                        HandleObjectGroup group,
                                                        size_t length);
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -1547,17 +1547,18 @@ static MOZ_MUST_USE JSObject* ReadableSt
     return nullptr;
   }
 
   // Step 3: Assert: Type(done) is Boolean (implicit).
 
   // Step 4: Let obj be ObjectCreate(prototype).
   NativeObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(
-      cx, obj, NativeObject::createWithTemplate(cx, templateObject));
+      cx, obj,
+      NativeObject::createWithTemplate(cx, gc::DefaultHeap, templateObject));
 
   // Step 5: Perform CreateDataProperty(obj, "value", value).
   obj->setSlot(Realm::IterResultObjectValueSlot, value);
 
   // Step 6: Perform CreateDataProperty(obj, "done", done).
   obj->setSlot(Realm::IterResultObjectDoneSlot,
                done ? TrueHandleValue : FalseHandleValue);
 
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-1532376.js
+++ /dev/null
@@ -1,10 +0,0 @@
-"use strict";
-function __f_276() {
-    this.getNameReallyHard = () => eval("eval('(() => this.name)()')")
-}
-for (var __v_1377 = 0; __v_1377 < 10000; __v_1377++) {
-  var __v_1378 = new __f_276();
-  try {
-    __v_1376[__getRandomProperty()];
-  } catch (e) {}
-__v_1378.getNameReallyHard()}
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2568,19 +2568,20 @@ bool BaselineCompilerCodeGen::emit_JSOP_
   JSObject* obj =
       ObjectGroup::getOrFixupCopyOnWriteObject(cx, scriptRoot, handler.pc());
   if (!obj) {
     return false;
   }
 
   prepareVMCall();
 
+  pushArg(Imm32(gc::DefaultHeap));
   pushArg(ImmGCPtr(obj));
 
-  using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject);
+  using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject, gc::InitialHeap);
   if (!callVM<Fn, js::NewDenseCopyOnWriteArray>()) {
     return false;
   }
 
   // Box and push return value.
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
   frame.push(R0);
   return true;
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6429,19 +6429,20 @@ void CodeGenerator::visitOutOfLineNewArr
 
 void CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
   ArrayObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
   // If we have a template object, we can inline call object creation.
-  using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject);
+  using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject, gc::InitialHeap);
   OutOfLineCode* ool = oolCallVM<Fn, js::NewDenseCopyOnWriteArray>(
-      lir, ArgList(ImmGCPtr(templateObject)), StoreRegisterTo(objReg));
+      lir, ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
+      StoreRegisterTo(objReg));
 
   TemplateObject templateObj(templateObject);
   templateObj.setDenseElementsAreCopyOnWrite();
   masm.createGCObject(objReg, tempReg, templateObj, initialHeap, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1249,28 +1249,32 @@ bool RNewArray::recover(JSContext* cx, S
   result.setObject(*resultObject);
   iter.storeInstructionResult(result);
   return true;
 }
 
 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) {}
+RNewArrayCopyOnWrite::RNewArrayCopyOnWrite(CompactBufferReader& reader) {
+  initialHeap_ = gc::InitialHeap(reader.readByte());
+}
 
 bool RNewArrayCopyOnWrite::recover(JSContext* cx,
                                    SnapshotIterator& iter) const {
   RootedArrayObject templateObject(cx,
                                    &iter.read().toObject().as<ArrayObject>());
   RootedValue result(cx);
 
-  ArrayObject* resultObject = NewDenseCopyOnWriteArray(cx, templateObject);
+  ArrayObject* resultObject =
+      NewDenseCopyOnWriteArray(cx, templateObject, initialHeap_);
   if (!resultObject) {
     return false;
   }
 
   result.setObject(*resultObject);
   iter.storeInstructionResult(result);
   return true;
 }
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -612,16 +612,19 @@ class RNewArray final : public RInstruct
  public:
   RINSTRUCTION_HEADER_NUM_OP_(NewArray, 1)
 
   MOZ_MUST_USE bool recover(JSContext* cx,
                             SnapshotIterator& iter) const override;
 };
 
 class RNewArrayCopyOnWrite final : public RInstruction {
+ private:
+  gc::InitialHeap initialHeap_;
+
  public:
   RINSTRUCTION_HEADER_NUM_OP_(NewArrayCopyOnWrite, 1)
 
   MOZ_MUST_USE bool recover(JSContext* cx,
                             SnapshotIterator& iter) const override;
 };
 
 class RNewIterator final : public RInstruction {
--- a/js/src/vm/ArrayObject-inl.h
+++ b/js/src/vm/ArrayObject-inl.h
@@ -37,18 +37,16 @@ inline void ArrayObject::setLength(JSCon
     HandleObjectGroup group, AutoSetNewObjectMetadata&) {
   const js::Class* clasp = group->clasp();
   MOZ_ASSERT(shape && group);
   MOZ_ASSERT(clasp == shape->getObjectClass());
   MOZ_ASSERT(clasp == &ArrayObject::class_);
   MOZ_ASSERT_IF(clasp->hasFinalize(), heap == gc::TenuredHeap);
   MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(),
                 heap == js::gc::TenuredHeap);
-  MOZ_ASSERT_IF(group->shouldPreTenureDontCheckGeneration(),
-                heap == gc::TenuredHeap);
 
   // Arrays can use their fixed slots to store elements, so can't have shapes
   // which allow named properties to be stored in the fixed slots.
   MOZ_ASSERT(shape->numFixedSlots() == 0);
 
   size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan(), clasp);
   JSObject* obj = js::AllocateObject(cx, kind, nDynamicSlots, heap, clasp);
   if (!obj) {
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -74,21 +74,19 @@ PropertyName* js::EnvironmentCoordinateN
 CallObject* CallObject::create(JSContext* cx, HandleShape shape,
                                HandleObjectGroup group) {
   MOZ_ASSERT(!group->singleton());
 
   gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
   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, heap, shape, group));
+  JS_TRY_VAR_OR_RETURN_NULL(
+      cx, obj, NativeObject::create(cx, kind, gc::DefaultHeap, shape, group));
 
   return &obj->as<CallObject>();
 }
 
 /*
  * Create a CallObject for a JSScript that is not initialized to any particular
  * callsite. This object can either be initialized (with an enclosing scope and
  * callee) or used as a template for jit compilation.
@@ -105,19 +103,16 @@ CallObject* CallObject::createTemplateOb
   if (!group) {
     return nullptr;
   }
 
   gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
   MOZ_ASSERT(CanBeFinalizedInBackground(kind, &class_));
   kind = gc::GetBackgroundAllocKind(kind);
 
-  // The JITs assume the result is nursery allocated unless we collected the
-  // nursery, so don't change |heap| here.
-
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(cx, obj,
                             NativeObject::create(cx, kind, heap, shape, group));
 
   CallObject* callObj = &obj->as<CallObject>();
   callObj->initEnclosingEnvironment(enclosing);
 
   if (scope->hasParameterExprs()) {
@@ -243,23 +238,16 @@ VarEnvironmentObject* VarEnvironmentObje
   if (!group) {
     return nullptr;
   }
 
   gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
   MOZ_ASSERT(CanBeFinalizedInBackground(kind, &class_));
   kind = gc::GetBackgroundAllocKind(kind);
 
-  {
-    AutoSweepObjectGroup sweep(group);
-    if (group->shouldPreTenure(sweep)) {
-      heap = gc::TenuredHeap;
-    }
-  }
-
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(cx, obj,
                             NativeObject::create(cx, kind, heap, shape, group));
 
   VarEnvironmentObject* env = &obj->as<VarEnvironmentObject>();
   MOZ_ASSERT(!env->inDictionaryMode());
   MOZ_ASSERT(env->isDelegate());
 
@@ -284,18 +272,19 @@ VarEnvironmentObject* VarEnvironmentObje
     MOZ_ASSERT_IF(
         frame.callee()->needsCallObject(),
         &frame.environmentChain()->as<CallObject>().callee() == frame.callee());
   }
 #endif
 
   RootedScript script(cx, frame.script());
   RootedObject envChain(cx, frame.environmentChain());
+  gc::InitialHeap heap = gc::DefaultHeap;
   RootedShape shape(cx, scope->environmentShape());
-  VarEnvironmentObject* env = create(cx, shape, envChain, gc::DefaultHeap);
+  VarEnvironmentObject* env = create(cx, shape, envChain, heap);
   if (!env) {
     return nullptr;
   }
   env->initScope(scope);
   return env;
 }
 
 /* static */
@@ -893,19 +882,16 @@ LexicalEnvironmentObject* LexicalEnviron
 
   RootedObjectGroup group(
       cx, ObjectGroup::defaultNewGroup(cx, &LexicalEnvironmentObject::class_,
                                        TaggedProto(nullptr)));
   if (!group) {
     return nullptr;
   }
 
-  // The JITs assume the result is nursery allocated unless we collected the
-  // nursery, so don't change |heap| here.
-
   gc::AllocKind allocKind = gc::GetGCObjectKind(shape->numFixedSlots());
   MOZ_ASSERT(
       CanBeFinalizedInBackground(allocKind, &LexicalEnvironmentObject::class_));
   allocKind = GetBackgroundAllocKind(allocKind);
 
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(
       cx, obj, NativeObject::create(cx, allocKind, heap, shape, group));
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5279,17 +5279,17 @@ ArrayObject* js::NewArrayCopyOnWriteOper
   MOZ_ASSERT(*pc == JSOP_NEWARRAY_COPYONWRITE);
 
   RootedArrayObject baseobj(
       cx, ObjectGroup::getOrFixupCopyOnWriteObject(cx, script, pc));
   if (!baseobj) {
     return nullptr;
   }
 
-  return NewDenseCopyOnWriteArray(cx, baseobj);
+  return NewDenseCopyOnWriteArray(cx, baseobj, gc::DefaultHeap);
 }
 
 void js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
                                    HandleId id) {
   MOZ_ASSERT(errorNumber == JSMSG_UNINITIALIZED_LEXICAL ||
              errorNumber == JSMSG_BAD_CONST_ASSIGN);
   if (UniqueChars printable =
           IdToPrintableUTF8(cx, id, IdToPrintableBehavior::IdIsIdentifier)) {
--- a/js/src/vm/Iteration.cpp
+++ b/js/src/vm/Iteration.cpp
@@ -575,17 +575,17 @@ static PropertyIteratorObject* NewProper
   if (!shape) {
     return nullptr;
   }
 
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(
       cx, obj,
       NativeObject::create(cx, ITERATOR_FINALIZE_KIND,
-                           GetInitialHeap(GenericObject, group), shape, group));
+                           GetInitialHeap(GenericObject, clasp), shape, group));
 
   PropertyIteratorObject* res = &obj->as<PropertyIteratorObject>();
 
   // CodeGenerator::visitIteratorStartO assumes the iterator object is not
   // inside the nursery when deciding whether a barrier is necessary.
   MOZ_ASSERT(!js::gc::IsInsideNursery(res));
 
   MOZ_ASSERT(res->numFixedSlots() == PropertyIteratorObject::NUM_FIXED_SLOTS);
@@ -942,17 +942,18 @@ JSObject* js::CreateIterResultObject(JSC
   RootedObject templateObject(
       cx, cx->realm()->getOrCreateIterResultTemplateObject(cx));
   if (!templateObject) {
     return nullptr;
   }
 
   NativeObject* resultObj;
   JS_TRY_VAR_OR_RETURN_NULL(
-      cx, resultObj, NativeObject::createWithTemplate(cx, templateObject));
+      cx, resultObj,
+      NativeObject::createWithTemplate(cx, gc::DefaultHeap, templateObject));
 
   // Step 3.
   resultObj->setSlot(Realm::IterResultObjectValueSlot, value);
 
   // Step 4.
   resultObj->setSlot(Realm::IterResultObjectDoneSlot,
                      done ? TrueHandleValue : FalseHandleValue);
 
--- a/js/src/vm/JSObject-inl.h
+++ b/js/src/vm/JSObject-inl.h
@@ -370,43 +370,16 @@ MOZ_ALWAYS_INLINE bool ToPropertyKey(JSC
  * its own object. Such a function object must not be accessible to script
  * or embedding code.
  */
 inline bool IsInternalFunctionObject(JSObject& funobj) {
   JSFunction& fun = funobj.as<JSFunction>();
   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) {
-  AutoSweepObjectGroup sweep(group);
-  if (group->shouldPreTenure(sweep)) {
-    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.
  */
 JSObject* NewObjectWithGivenTaggedProto(JSContext* cx, const Class* clasp,
                                         Handle<TaggedProto> proto,
                                         gc::AllocKind allocKind,
                                         NewObjectKind newKind,
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -786,17 +786,17 @@ static inline JSObject* NewObject(JSCont
                       : GetGCKindSlots(kind, clasp);
 
   RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(),
                                                     nfixed, initialShapeFlags));
   if (!shape) {
     return nullptr;
   }
 
-  gc::InitialHeap heap = GetInitialHeap(newKind, group);
+  gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
 
   JSObject* obj;
   if (clasp->isJSFunction()) {
     JS_TRY_VAR_OR_RETURN_NULL(cx, obj,
                               JSFunction::create(cx, kind, heap, shape, group));
   } else if (MOZ_LIKELY(clasp->isNative())) {
     JS_TRY_VAR_OR_RETURN_NULL(
         cx, obj, NativeObject::create(cx, kind, heap, shape, group));
@@ -968,18 +968,18 @@ JSObject* js::NewObjectWithGroupCommon(J
     allocKind = GetBackgroundAllocKind(allocKind);
   }
 
   bool isCachable = NewObjectWithGroupIsCachable(cx, group, newKind);
   if (isCachable) {
     NewObjectCache& cache = cx->caches().newObjectCache;
     NewObjectCache::EntryIndex entry = -1;
     if (cache.lookupGroup(group, allocKind, &entry)) {
-      JSObject* obj =
-          cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, group));
+      JSObject* obj = cache.newObjectFromHit(
+          cx, entry, GetInitialHeap(newKind, group->clasp()));
       if (obj) {
         return obj;
       }
     }
   }
 
   JSObject* obj = NewObject(cx, group, allocKind, newKind);
   if (!obj) {
@@ -4232,23 +4232,16 @@ void JSObject::debugCheckNewObject(Objec
 
   MOZ_ASSERT_IF(clasp->hasFinalize(),
                 heap == gc::TenuredHeap ||
                     CanNurseryAllocateFinalizedClass(clasp) ||
                     clasp->isProxy());
   MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(),
                 heap == gc::TenuredHeap);
 
-  // Check that the group's shouldPreTenure flag is respected but ignore
-  // environment objects that the JIT expects to be nursery allocated.
-  MOZ_ASSERT_IF(group->shouldPreTenureDontCheckGeneration() &&
-                    clasp != &CallObject::class_ &&
-                    clasp != &LexicalEnvironmentObject::class_,
-                heap == gc::TenuredHeap);
-
   MOZ_ASSERT(!group->realm()->hasObjectPendingMetadata());
 
   // Non-native classes manage their own data and slots, so numFixedSlots and
   // slotSpan are always 0. Note that proxy classes can have reserved slots
   // but they're also not included in numFixedSlots/slotSpan.
   if (!clasp->isNative()) {
     MOZ_ASSERT_IF(!clasp->isProxy(), JSCLASS_RESERVED_SLOTS(clasp) == 0);
     MOZ_ASSERT(!clasp->hasPrivate());
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -793,16 +793,33 @@ Value GetThisValueOfWith(JSObject* env);
 
 using ClassInitializerOp = JSObject* (*)(JSContext* cx,
                                          Handle<GlobalObject*> global);
 
 } /* namespace js */
 
 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,
                                         const Class* clasp);
 
 // ES6 9.1.15 GetPrototypeFromConstructor.
 extern bool GetPrototypeFromConstructor(JSContext* cx,
                                         js::HandleObject newTarget,
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -517,21 +517,19 @@ inline bool NativeObject::isInWholeCellB
   }
 
   js::gc::gcTracer.traceCreateObject(nobj);
 
   return nobj;
 }
 
 /* static */ inline JS::Result<NativeObject*, JS::OOM&>
-NativeObject::createWithTemplate(JSContext* cx, HandleObject templateObject) {
+NativeObject::createWithTemplate(JSContext* cx, js::gc::InitialHeap heap,
+                                 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());
   MOZ_ASSERT(CanBeFinalizedInBackground(kind, shape->getObjectClass()));
   kind = gc::GetBackgroundAllocKind(kind);
 
   return create(cx, kind, heap, shape, group);
 }
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -554,17 +554,17 @@ class NativeObject : public ShapedObject
 
   inline bool isInWholeCellBuffer() const;
 
   static inline JS::Result<NativeObject*, JS::OOM&> create(
       JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
       js::HandleShape shape, js::HandleObjectGroup group);
 
   static inline JS::Result<NativeObject*, JS::OOM&> createWithTemplate(
-      JSContext* cx, HandleObject templateObject);
+      JSContext* cx, js::gc::InitialHeap heap, HandleObject templateObject);
 
 #ifdef DEBUG
   static void enableShapeConsistencyChecks();
 #endif
 
  protected:
 #ifdef DEBUG
   friend class js::AutoCheckShapeConsistency;
--- a/js/src/vm/ObjectGroup-inl.h
+++ b/js/src/vm/ObjectGroup-inl.h
@@ -49,23 +49,18 @@ inline bool ObjectGroup::hasAllFlags(con
 
 inline bool ObjectGroup::unknownProperties(const AutoSweepObjectGroup& sweep) {
   MOZ_ASSERT_IF(flags(sweep) & OBJECT_FLAG_UNKNOWN_PROPERTIES,
                 hasAllFlags(sweep, OBJECT_FLAG_DYNAMIC_MASK));
   return !!(flags(sweep) & OBJECT_FLAG_UNKNOWN_PROPERTIES);
 }
 
 inline bool ObjectGroup::shouldPreTenure(const AutoSweepObjectGroup& sweep) {
-  MOZ_ASSERT(sweep.group() == this);
-  return shouldPreTenureDontCheckGeneration();
-}
-
-inline bool ObjectGroup::shouldPreTenureDontCheckGeneration() {
-  return hasAnyFlagsDontCheckGeneration(OBJECT_FLAG_PRE_TENURE) &&
-         !unknownPropertiesDontCheckGeneration();
+  return hasAnyFlags(sweep, OBJECT_FLAG_PRE_TENURE) &&
+         !unknownProperties(sweep);
 }
 
 inline bool ObjectGroup::canPreTenure(const AutoSweepObjectGroup& sweep) {
   return !unknownProperties(sweep);
 }
 
 inline bool ObjectGroup::fromAllocationSite(const AutoSweepObjectGroup& sweep) {
   return flags(sweep) & OBJECT_FLAG_FROM_ALLOCATION_SITE;
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -344,35 +344,30 @@ class ObjectGroup : public gc::TenuredCe
   inline ObjectGroup(const Class* clasp, TaggedProto proto, JS::Realm* realm,
                      ObjectGroupFlags initialFlags);
 
   inline bool hasAnyFlags(const AutoSweepObjectGroup& sweep,
                           ObjectGroupFlags flags);
   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;
   }
 
   inline bool unknownProperties(const AutoSweepObjectGroup& sweep);
 
   bool unknownPropertiesDontCheckGeneration() {
     MOZ_ASSERT_IF(flagsDontCheckGeneration() & OBJECT_FLAG_UNKNOWN_PROPERTIES,
                   hasAllFlagsDontCheckGeneration(OBJECT_FLAG_DYNAMIC_MASK));
     return !!(flagsDontCheckGeneration() & OBJECT_FLAG_UNKNOWN_PROPERTIES);
   }
 
   inline bool shouldPreTenure(const AutoSweepObjectGroup& sweep);
-  inline bool shouldPreTenureDontCheckGeneration();
 
   gc::InitialHeap initialHeap(CompilerConstraintList* constraints);
 
   inline bool canPreTenure(const AutoSweepObjectGroup& sweep);
   inline bool fromAllocationSite(const AutoSweepObjectGroup& sweep);
   inline void setShouldPreTenure(const AutoSweepObjectGroup& sweep,
                                  JSContext* cx);
 
--- a/js/src/vm/ProxyObject.cpp
+++ b/js/src/vm/ProxyObject.cpp
@@ -179,17 +179,17 @@ void ProxyObject::nuke() {
     if (!shape) {
       return cx->alreadyReportedOOM();
     }
 
     MOZ_ASSERT(group->realm() == realm);
     realm->newProxyCache.add(group, shape);
   }
 
-  gc::InitialHeap heap = GetInitialHeap(newKind, group);
+  gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
   debugCheckNewObject(group, shape, allocKind, heap);
 
   JSObject* obj =
       js::AllocateObject(cx, allocKind, /* nDynamicSlots = */ 0, heap, clasp);
   if (!obj) {
     return cx->alreadyReportedOOM();
   }
 
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -870,17 +870,17 @@ UnboxedPlainObject* UnboxedPlainObject::
 
   MOZ_ASSERT(group->clasp() == &class_);
 
   gc::AllocKind allocKind;
   {
     AutoSweepObjectGroup sweep(group);
     allocKind = group->unboxedLayout(sweep).getAllocKind();
   }
-  gc::InitialHeap heap = GetInitialHeap(newKind, group);
+  gc::InitialHeap heap = GetInitialHeap(newKind, &class_);
 
   MOZ_ASSERT(newKind != SingletonObject);
 
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(cx, obj,
                             createInternal(cx, allocKind, heap, group));
 
   UnboxedPlainObject* uobj = static_cast<UnboxedPlainObject*>(obj);