Backed out 2 changesets (bug 1532376) for causing Bug 1534118 a=backout FIREFOX_BETA_67_BASE
authorGurzau Raul <rgurzau@mozilla.com>
Mon, 11 Mar 2019 12:27:26 +0200
changeset 521310 f4c23517cec8626038a915bfe3bc7c0e1f6af55d
parent 521309 cdb2110b85f32263e6213ee39e6cc9dc37945a03
child 521311 0bf136f3ac45ce5e1c5d76c9c89d2fed6d15d0c4
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1532376, 1534118
milestone67.0a1
backs out82a1c708780619b605a5c0f63cd8046f3e992692
1b4fd78107e2bcf7fe0f44038176ca745b07cd88
first release with
nightly linux32
f4c23517cec8 / 67.0a1 / 20190311102806 / files
nightly linux64
f4c23517cec8 / 67.0a1 / 20190311102806 / files
nightly mac
f4c23517cec8 / 67.0a1 / 20190311102806 / files
nightly win32
f4c23517cec8 / 67.0a1 / 20190311102806 / files
nightly win64
f4c23517cec8 / 67.0a1 / 20190311102806 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 2 changesets (bug 1532376) for causing Bug 1534118 a=backout Backed out changeset 82a1c7087806 (bug 1532376) Backed out changeset 1b4fd78107e2 (bug 1532376)
js/src/builtin/Array.cpp
js/src/builtin/Array.h
js/src/builtin/Stream.cpp
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
@@ -4059,17 +4059,17 @@ static MOZ_ALWAYS_INLINE ArrayObject* Ne
                                                     gc::AllocKind::OBJECT0));
   if (!shape) {
     return nullptr;
   }
 
   AutoSetNewObjectMetadata metadata(cx);
   RootedArrayObject arr(
       cx, ArrayObject::createArray(
-              cx, allocKind, GetInitialHeap(newKind, group),
+              cx, allocKind, GetInitialHeap(newKind, &ArrayObject::class_),
               shape, group, length, metadata));
   if (!arr) {
     return nullptr;
   }
 
   if (shape->isEmptyShape()) {
     if (!AddLengthProperty(cx, arr)) {
       return nullptr;
@@ -4148,17 +4148,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)) {
@@ -4166,21 +4166,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
@@ -1548,17 +1548,17 @@ static MOZ_MUST_USE JSObject* ReadableSt
   }
 
   // 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));
+      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);
 
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2570,19 +2570,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
@@ -6533,31 +6533,32 @@ void CodeGenerator::visitNewArray(LNewAr
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitOutOfLineNewArray(OutOfLineNewArray* ool) {
   visitNewArrayCallVM(ool->lir());
   masm.jump(ool->rejoin());
 }
 
-typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject);
+typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject,
+                                              gc::InitialHeap);
 static const VMFunction NewArrayCopyOnWriteInfo =
     FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray,
                                         "NewDenseCopyOnWriteArray");
 
 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.
   OutOfLineCode* ool =
       oolCallVM(NewArrayCopyOnWriteInfo, lir,
-                ArgList(ImmGCPtr(templateObject)),
+                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,30 +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) {
+  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);
+      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::Allocate<JSObject>(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));
+      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,20 +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);
 
-  if (group->shouldPreTenureDontCheckGeneration()) {
-    heap = gc::TenuredHeap;
-  }
-
   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()) {
@@ -888,20 +882,16 @@ LexicalEnvironmentObject* LexicalEnviron
 
   RootedObjectGroup group(
       cx, ObjectGroup::defaultNewGroup(cx, &LexicalEnvironmentObject::class_,
                                        TaggedProto(nullptr)));
   if (!group) {
     return nullptr;
   }
 
-  if (group->shouldPreTenureDontCheckGeneration()) {
-    heap = gc::TenuredHeap;
-  }
-
   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
@@ -5297,17 +5297,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
@@ -614,17 +614,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);
@@ -991,17 +991,17 @@ JSObject* js::CreateIterResultObject(JSC
       cx, cx->realm()->getOrCreateIterResultTemplateObject(cx));
   if (!templateObject) {
     return nullptr;
   }
 
   NativeObject* resultObj;
   JS_TRY_VAR_OR_RETURN_NULL(
       cx, resultObj,
-      NativeObject::createWithTemplate(cx, templateObject));
+      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
@@ -394,42 +394,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) {
-  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.
  */
 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
@@ -787,17 +787,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));
@@ -970,17 +970,17 @@ JSObject* js::NewObjectWithGroupCommon(J
   }
 
   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));
+          cx, entry, GetInitialHeap(newKind, group->clasp()));
       if (obj) {
         return obj;
       }
     }
   }
 
   JSObject* obj = NewObject(cx, group, allocKind, newKind);
   if (!obj) {
@@ -4291,18 +4291,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);
-  MOZ_ASSERT_IF(group->shouldPreTenureDontCheckGeneration(),
-                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);
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -797,16 +797,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
@@ -560,17 +560,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
@@ -399,35 +399,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::Allocate<JSObject>(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);