Merge mozilla-central to autoland. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Mon, 11 Mar 2019 18:54:51 +0200
changeset 521405 551105fd7f8137dc15533b35eb304ed32829de7f
parent 521404 835b87c028dd8e134ceb83fa575abffa53321f8e (current diff)
parent 521351 eb0a25f393aad44362b34f21173193f6f632d2eb (diff)
child 521406 e5897543e5e6d850ab5953c523de8eaa5be9a300
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.0a1
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
Merge mozilla-central to autoland. a=merge CLOSED TREE
--- a/.hgtags
+++ b/.hgtags
@@ -153,8 +153,9 @@ 224715760a637bc37c14794839468a954f1f2695
 224715760a637bc37c14794839468a954f1f2695 FIREFOX_BETA_64_BASE
 ad179a6fc14cbd41d10a018ac4a3822db119de3b FIREFOX_BETA_64_BASE
 c44fbdd5173548c9035256dda8fd3512f67118a8 FIREFOX_NIGHTLY_64_END
 58a0412e15574f063cd380517a0369bfb48b22e0 PRE_TREEWIDE_CLANG_FORMAT
 9ad82455dcee2bc1d438e46016b8db00e88758a8 FIREFOX_BETA_65_BASE
 3386ff76878d83496bb822d09115c77472808b53 FIREFOX_NIGHTLY_65_END
 254bd88c107271f3d1c2ca9969acc0ed507f0a8d FIREFOX_BETA_66_BASE
 5d9c5aa981a5b824e6132c923c2f201b3fa49397 FIREFOX_NIGHTLY_66_END
+f4c23517cec8626038a915bfe3bc7c0e1f6af55d FIREFOX_BETA_67_BASE
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -4071,17 +4071,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;
@@ -4160,17 +4160,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)) {
@@ -4178,21 +4178,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::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));
+      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
@@ -5298,17 +5298,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::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);