Bug 1165486 - Cleanup: use standard object allocation functions when allocating scope objects. (r=terrence)
☠☠ backed out by b7e3bb16f653 ☠ ☠
authorShu-yu Guo <shu@rfrn.org>
Mon, 15 Jun 2015 17:38:01 -0700
changeset 279767 ccd90228daf67dda2b82c52dbb5da442f0ae7d58
parent 279766 eb11e655d223ff83240f7a3d5e5e742ce4edbcfe
child 279768 e3c11d517e186ca29e3af1477378ff66a116a3f2
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1165486
milestone41.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
Bug 1165486 - Cleanup: use standard object allocation functions when allocating scope objects. (r=terrence)
js/src/jit/BaselineCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/vm/ScopeObject.cpp
js/src/vm/ScopeObject.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -15,16 +15,17 @@
 #include "jit/JitcodeMap.h"
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/SharedICHelpers.h"
 #include "jit/VMFunctions.h"
+#include "vm/ScopeObject.h"
 #include "vm/TraceLogging.h"
 
 #include "jsscriptinlines.h"
 
 #include "vm/Interpreter-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
@@ -123,17 +124,17 @@ BaselineCompiler::compile()
         RootedFunction fun(cx, script->functionNonDelazifying());
         if (fun->isHeavyweight()) {
             RootedScript scriptRoot(cx, script);
             templateScope = CallObject::createTemplateObject(cx, scriptRoot, gc::TenuredHeap);
             if (!templateScope)
                 return Method_Error;
 
             if (fun->isNamedLambda()) {
-                RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
+                RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, TenuredObject));
                 if (!declEnvObject)
                     return Method_Error;
                 templateScope->as<ScopeObject>().setEnclosingScope(declEnvObject);
             }
         }
     }
 
     // Encode the pc mapping table. See PCMappingIndexEntry for
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4678,31 +4678,31 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox
         break;
       default:
         MOZ_CRASH("The impossible happened!");
     }
 
     bailoutFrom(&bail, lir->snapshot());
 }
 
-typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, gc::InitialHeap);
+typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, NewObjectKind);
 static const VMFunction NewDeclEnvObjectInfo =
     FunctionInfo<NewDeclEnvObjectFn>(DeclEnvObject::createTemplateObject);
 
 void
 CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject* lir)
 {
     Register objReg = ToRegister(lir->output());
     Register tempReg = ToRegister(lir->temp());
     DeclEnvObject* templateObj = lir->mir()->templateObj();
     CompileInfo& info = lir->mir()->block()->info();
 
     // If we have a template object, we can inline call object creation.
     OutOfLineCode* ool = oolCallVM(NewDeclEnvObjectInfo, lir,
-                                   ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)),
+                                   ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(GenericObject)),
                                    StoreRegisterTo(objReg));
 
     bool initContents = ShouldInitFixedSlots(lir, templateObj);
     masm.createGCObject(objReg, tempReg, templateObj, gc::DefaultHeap, ool->entry(),
                         initContents);
 
     masm.bind(ool->rejoin());
 }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1071,32 +1071,33 @@ NewObjectGCKind(const js::Class* clasp)
         return gc::AllocKind::OBJECT8;
     if (clasp == &JSFunction::class_)
         return gc::AllocKind::OBJECT2;
     return gc::AllocKind::OBJECT4;
 }
 
 static inline JSObject*
 NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
-          NewObjectKind newKind)
+          NewObjectKind newKind, uint32_t initialShapeFlags = 0)
 {
     const Class* clasp = group->clasp();
 
     MOZ_ASSERT(clasp != &ArrayObject::class_);
     MOZ_ASSERT_IF(clasp == &JSFunction::class_,
                   kind == AllocKind::FUNCTION || kind == AllocKind::FUNCTION_EXTENDED);
 
     // For objects which can have fixed data following the object, only use
     // enough fixed slots to cover the number of reserved slots in the object,
     // regardless of the allocation kind specified.
     size_t nfixed = ClassCanHaveFixedData(clasp)
                     ? GetGCKindSlots(gc::GetGCObjectKind(clasp), clasp)
                     : GetGCKindSlots(kind, clasp);
 
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed));
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed,
+                                                      initialShapeFlags));
     if (!shape)
         return nullptr;
 
     gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
     JSObject* obj = JSObject::create(cx, kind, heap, shape, group);
     if (!obj)
         return nullptr;
 
@@ -1134,17 +1135,18 @@ NewObjectWithTaggedProtoIsCachable(Exclu
            newKind == GenericObject &&
            clasp->isNative() &&
            !proto.toObject()->is<GlobalObject>();
 }
 
 JSObject*
 js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
                                   Handle<TaggedProto> proto,
-                                  gc::AllocKind allocKind, NewObjectKind newKind)
+                                  gc::AllocKind allocKind, NewObjectKind newKind,
+                                  uint32_t initialShapeFlags)
 {
     if (CanBeFinalizedInBackground(allocKind, clasp))
         allocKind = GetBackgroundAllocKind(allocKind);
 
     bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, proto, newKind, clasp);
     if (isCachable) {
         JSContext* cx = cxArg->asJSContext();
         JSRuntime* rt = cx->runtime();
@@ -1156,17 +1158,17 @@ js::NewObjectWithGivenTaggedProto(Exclus
                 return obj;
         }
     }
 
     RootedObjectGroup group(cxArg, ObjectGroup::defaultNewGroup(cxArg, clasp, proto, nullptr));
     if (!group)
         return nullptr;
 
-    RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind));
+    RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind, initialShapeFlags));
     if (!obj)
         return nullptr;
 
     if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
         NewObjectCache& cache = cxArg->asJSContext()->runtime()->newObjectCache;
         NewObjectCache::EntryIndex entry = -1;
         cache.lookupProto(clasp, proto.toObject(), allocKind, &entry);
         cache.fillProto(entry, clasp, proto, allocKind, &obj->as<NativeObject>());
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -598,35 +598,48 @@ IsInternalFunctionObject(JSObject* funob
 typedef AutoVectorRooter<PropertyDescriptor> AutoPropertyDescriptorVector;
 
 /*
  * 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(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
-                              gc::AllocKind allocKind, NewObjectKind newKind);
+                              gc::AllocKind allocKind, NewObjectKind newKind,
+                              uint32_t initialShapeFlags = 0);
 
 inline JSObject*
 NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
-                              NewObjectKind newKind = GenericObject)
+                              NewObjectKind newKind = GenericObject,
+                              uint32_t initialShapeFlags = 0)
 {
     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
-    return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind);
+    return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind, initialShapeFlags);
 }
 
 template <typename T>
 inline T*
 NewObjectWithGivenTaggedProto(ExclusiveContext* cx, Handle<TaggedProto> proto,
-                              NewObjectKind newKind = GenericObject)
+                              NewObjectKind newKind = GenericObject,
+                              uint32_t initialShapeFlags = 0)
 {
-    JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind);
+    JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind,
+                                                  initialShapeFlags);
     return obj ? &obj->as<T>() : nullptr;
 }
 
+template <typename T>
+inline T*
+NewObjectWithNullTaggedProto(ExclusiveContext* cx, NewObjectKind newKind = GenericObject,
+                             uint32_t initialShapeFlags = 0)
+{
+    Rooted<TaggedProto> nullProto(cx, TaggedProto(nullptr));
+    return NewObjectWithGivenTaggedProto<T>(cx, nullProto, newKind, initialShapeFlags);
+}
+
 inline JSObject*
 NewObjectWithGivenProto(ExclusiveContext* cx, const Class* clasp, HandleObject proto,
                         gc::AllocKind allocKind, NewObjectKind newKind)
 {
     return NewObjectWithGivenTaggedProto(cx, clasp, AsTaggedProto(proto), allocKind,
                                          newKind);
 }
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -318,32 +318,20 @@ const Class DeclEnvObject::class_ = {
 };
 
 /*
  * Create a DeclEnvObject 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.
  */
 DeclEnvObject*
-DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap)
+DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind)
 {
-    MOZ_ASSERT(IsNurseryAllocable(FINALIZE_KIND));
-
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
-    if (!group)
-        return nullptr;
-
-    RootedShape emptyDeclEnvShape(cx);
-    emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
-                                                    FINALIZE_KIND, BaseShape::DELEGATE);
-    if (!emptyDeclEnvShape)
-        return nullptr;
-
-    RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND, heap,
-                                                                  emptyDeclEnvShape, group)));
+    Rooted<DeclEnvObject*> obj(cx);
+    obj = NewObjectWithNullTaggedProto<DeclEnvObject>(cx, newKind, BaseShape::DELEGATE);
     if (!obj)
         return nullptr;
 
     // Assign a fixed slot to a property with the same name as the lambda.
     Rooted<jsid> id(cx, AtomToId(fun->atom()));
     const Class* clasp = obj->getClass();
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY;
 
@@ -351,23 +339,23 @@ DeclEnvObject::createTemplateObject(JSCo
     JSSetterOp setter = clasp->setProperty;
     MOZ_ASSERT(getter != JS_PropertyStub);
     MOZ_ASSERT(setter != JS_StrictPropertyStub);
 
     if (!NativeObject::putProperty(cx, obj, id, getter, setter, lambdaSlot(), attrs, 0))
         return nullptr;
 
     MOZ_ASSERT(!obj->hasDynamicSlots());
-    return &obj->as<DeclEnvObject>();
+    return obj;
 }
 
 DeclEnvObject*
 DeclEnvObject::create(JSContext* cx, HandleObject enclosing, HandleFunction callee)
 {
-    Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, gc::DefaultHeap));
+    Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, GenericObject));
     if (!obj)
         return nullptr;
 
     obj->setEnclosingScope(enclosing);
     obj->setFixedSlot(lambdaSlot(), ObjectValue(*callee));
     return obj;
 }
 
@@ -395,30 +383,17 @@ template bool
 js::XDRStaticWithObject(XDRState<XDR_ENCODE>*, HandleObject, MutableHandle<StaticWithObject*>);
 
 template bool
 js::XDRStaticWithObject(XDRState<XDR_DECODE>*, HandleObject, MutableHandle<StaticWithObject*>);
 
 StaticWithObject*
 StaticWithObject::create(ExclusiveContext* cx)
 {
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
-    if (!group)
-        return nullptr;
-
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
-                                                      FINALIZE_KIND));
-    if (!shape)
-        return nullptr;
-
-    RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, shape, group));
-    if (!obj)
-        return nullptr;
-
-    return &obj->as<StaticWithObject>();
+    return NewObjectWithNullTaggedProto<StaticWithObject>(cx, TenuredObject, BaseShape::DELEGATE);
 }
 
 static JSObject*
 CloneStaticWithObject(JSContext* cx, HandleObject enclosingScope, Handle<StaticWithObject*> srcWith)
 {
     Rooted<StaticWithObject*> clone(cx, StaticWithObject::create(cx));
     if (!clone)
         return nullptr;
@@ -428,41 +403,34 @@ CloneStaticWithObject(JSContext* cx, Han
     return clone;
 }
 
 DynamicWithObject*
 DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclosing,
                           HandleObject staticWith, WithKind kind)
 {
     MOZ_ASSERT(staticWith->is<StaticWithObject>());
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_,
-                                                             TaggedProto(staticWith.get())));
-    if (!group)
-        return nullptr;
-
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(staticWith),
-                                                      FINALIZE_KIND));
-    if (!shape)
-        return nullptr;
-
-    RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
-                                                                  gc::DefaultHeap, shape, group)));
+
+    Rooted<TaggedProto> proto(cx, TaggedProto(staticWith));
+    Rooted<DynamicWithObject*> obj(cx);
+    obj = NewObjectWithGivenTaggedProto<DynamicWithObject>(cx, proto, GenericObject,
+                                                           BaseShape::DELEGATE);
     if (!obj)
         return nullptr;
 
     JSObject* thisp = GetThisObject(cx, object);
     if (!thisp)
         return nullptr;
 
     obj->as<ScopeObject>().setEnclosingScope(enclosing);
     obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
     obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
     obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
 
-    return &obj->as<DynamicWithObject>();
+    return obj;
 }
 
 static bool
 with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
                     MutableHandleObject objp, MutableHandleShape propp)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return LookupProperty(cx, actual, id, objp, propp);
@@ -562,33 +530,24 @@ const Class DynamicWithObject::class_ = 
         nullptr,             /* enumerate (native enumeration of target doesn't work) */
         with_ThisObject,
     }
 };
 
 /* static */ StaticEvalObject*
 StaticEvalObject::create(JSContext* cx, HandleObject enclosing)
 {
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
-    if (!group)
-        return nullptr;
-
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
-                                                      FINALIZE_KIND, BaseShape::DELEGATE));
-    if (!shape)
-        return nullptr;
-
-    RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
-                                                                  gc::TenuredHeap, shape, group)));
+    StaticEvalObject* obj =
+        NewObjectWithNullTaggedProto<StaticEvalObject>(cx, TenuredObject, BaseShape::DELEGATE);
     if (!obj)
         return nullptr;
 
     obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
     obj->setReservedSlot(STRICT_SLOT, BooleanValue(false));
-    return &obj->as<StaticEvalObject>();
+    return obj;
 }
 
 const Class StaticEvalObject::class_ = {
     "StaticEval",
     JSCLASS_HAS_RESERVED_SLOTS(StaticEvalObject::RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS
 };
 
@@ -601,17 +560,20 @@ ClonedBlockObject::create(JSContext* cx,
 
     RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &BlockObject::class_,
                                                              TaggedProto(block.get())));
     if (!group)
         return nullptr;
 
     RootedShape shape(cx, block->lastProperty());
 
-    RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
+    gc::AllocKind allocKind = gc::GetGCObjectKind(&BlockObject::class_);
+    if (CanBeFinalizedInBackground(allocKind, &BlockObject::class_))
+        allocKind = GetBackgroundAllocKind(allocKind);
+    RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, allocKind,
                                                                   gc::TenuredHeap, shape, group)));
     if (!obj)
         return nullptr;
 
     MOZ_ASSERT(!obj->inDictionaryMode());
     MOZ_ASSERT(obj->slotSpan() >= block->numVariables() + RESERVED_SLOTS);
 
     obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*enclosing));
@@ -675,32 +637,17 @@ ClonedBlockObject::clone(JSContext* cx, 
         copy->setVar(i, clonedBlock->var(i, DONT_CHECK_ALIASING), DONT_CHECK_ALIASING);
 
     return copy;
 }
 
 StaticBlockObject*
 StaticBlockObject::create(ExclusiveContext* cx)
 {
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &BlockObject::class_,
-                                                             TaggedProto(nullptr)));
-    if (!group)
-        return nullptr;
-
-    RootedShape emptyBlockShape(cx);
-    emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockObject::class_, TaggedProto(nullptr),
-                                                  FINALIZE_KIND, BaseShape::DELEGATE);
-    if (!emptyBlockShape)
-        return nullptr;
-
-    JSObject* obj = JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, emptyBlockShape, group);
-    if (!obj)
-        return nullptr;
-
-    return &obj->as<StaticBlockObject>();
+    return NewObjectWithNullTaggedProto<StaticBlockObject>(cx, TenuredObject, BaseShape::DELEGATE);
 }
 
 /* static */ Shape*
 StaticBlockObject::addVar(ExclusiveContext* cx, Handle<StaticBlockObject*> block, HandleId id,
                           bool constant, unsigned index, bool* redeclared)
 {
     MOZ_ASSERT(JSID_IS_ATOM(id));
     MOZ_ASSERT(index < LOCAL_INDEX_LIMIT);
@@ -888,32 +835,23 @@ js::CloneNestedScopeObject(JSContext* cx
         Rooted<StaticWithObject*> withObj(cx, &srcBlock->as<StaticWithObject>());
         return CloneStaticWithObject(cx, enclosingScope, withObj);
     }
 }
 
 /* static */ UninitializedLexicalObject*
 UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
 {
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
-    if (!group)
-        return nullptr;
-
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
-                                                      FINALIZE_KIND));
-    if (!shape)
-        return nullptr;
-
-    RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::DefaultHeap, shape, group));
+    UninitializedLexicalObject* obj =
+        NewObjectWithNullTaggedProto<UninitializedLexicalObject>(cx, GenericObject,
+                                                                 BaseShape::DELEGATE);
     if (!obj)
         return nullptr;
-
     obj->as<ScopeObject>().setEnclosingScope(enclosing);
-
-    return &obj->as<UninitializedLexicalObject>();
+    return obj;
 }
 
 static void
 ReportUninitializedLexicalId(JSContext* cx, HandleId id)
 {
     if (JSID_IS_ATOM(id)) {
         RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
         ReportUninitializedLexical(cx, name);
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -335,40 +335,36 @@ class CallObject : public ScopeObject
 
 class DeclEnvObject : public ScopeObject
 {
     // Pre-allocated slot for the named lambda.
     static const uint32_t LAMBDA_SLOT = 1;
 
   public:
     static const uint32_t RESERVED_SLOTS = 2;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
-
     static const Class class_;
 
     static DeclEnvObject*
-    createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap);
+    createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind);
 
     static DeclEnvObject* create(JSContext* cx, HandleObject enclosing, HandleFunction callee);
 
     static inline size_t lambdaSlot() {
         return LAMBDA_SLOT;
     }
 };
 
 // Static eval scope template objects on the static scope. Created at the
 // time of compiling the eval script, and set as its static enclosing scope.
 class StaticEvalObject : public ScopeObject
 {
     static const uint32_t STRICT_SLOT = 1;
 
   public:
     static const unsigned RESERVED_SLOTS = 2;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
-
     static const Class class_;
 
     static StaticEvalObject* create(JSContext* cx, HandleObject enclosing);
 
     JSObject* enclosingScopeForStaticScopeIter() {
         return getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
     }
 
@@ -431,34 +427,30 @@ class NestedScopeObject : public ScopeOb
     }
 };
 
 // With scope template objects on the static scope chain.
 class StaticWithObject : public NestedScopeObject
 {
   public:
     static const unsigned RESERVED_SLOTS = 1;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
-
     static const Class class_;
 
     static StaticWithObject* create(ExclusiveContext* cx);
 };
 
 // With scope objects on the run-time scope chain.
 class DynamicWithObject : public NestedScopeObject
 {
     static const unsigned OBJECT_SLOT = 1;
     static const unsigned THIS_SLOT = 2;
     static const unsigned KIND_SLOT = 3;
 
   public:
     static const unsigned RESERVED_SLOTS = 4;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
-
     static const Class class_;
 
     enum WithKind {
         SyntacticWith,
         NonSyntacticWith
     };
 
     static DynamicWithObject*
@@ -500,18 +492,16 @@ class DynamicWithObject : public NestedS
 
 class BlockObject : public NestedScopeObject
 {
   protected:
     static const unsigned DEPTH_SLOT = 1;
 
   public:
     static const unsigned RESERVED_SLOTS = 2;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
-
     static const Class class_;
 
     /* Return the abstract stack depth right before entering this nested scope. */
     uint32_t stackDepth() const {
         return getReservedSlot(DEPTH_SLOT).toPrivateUint32();
     }
 
     /* Return the number of variables associated with this block. */
@@ -588,17 +578,17 @@ class StaticBlockObject : public BlockOb
         return slotValue(i).isTrue();
     }
 
     /*
      * A static block object is cloned (when entering the block) iff some
      * variable of the block isAliased.
      */
     bool needsClone() {
-        return !getFixedSlot(RESERVED_SLOTS).isFalse();
+        return numVariables() > 0 && !getSlot(RESERVED_SLOTS).isFalse();
     }
 
     /* Frontend-only functions ***********************************************/
 
     /* Initialization functions for above fields. */
     void setAliased(unsigned i, bool aliased) {
         MOZ_ASSERT_IF(i > 0, slotValue(i-1).isBoolean());
         setSlotValue(i, BooleanValue(aliased));
@@ -692,18 +682,16 @@ class ClonedBlockObject : public BlockOb
 // demands that the error be thrown after evaluating the RHS of
 // assignments. Instead, this sentinel scope object is pushed on the stack.
 // Attempting to access anything on this scope throws the appropriate
 // ReferenceError.
 class UninitializedLexicalObject : public ScopeObject
 {
   public:
     static const unsigned RESERVED_SLOTS = 1;
-    static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
-
     static const Class class_;
 
     static UninitializedLexicalObject* create(JSContext* cx, HandleObject enclosing);
 };
 
 template<XDRMode mode>
 bool
 XDRStaticBlockObject(XDRState<mode>* xdr, HandleObject enclosingScope,