Bug 1320408 - Part 4: Change JSObject::getGroup to static method. r=jandem
authorTooru Fujisawa <arai_a@mac.com>
Sat, 31 Dec 2016 16:03:01 +0900
changeset 372731 3d2ebd012bd504f744cfb638100a6429e7349b86
parent 372730 5d73103c498b3fcb2811faa23266e9e4311df0eb
child 372732 1d62e09d7c87f8464b00316de4402fea381453b9
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1320408
milestone53.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 1320408 - Part 4: Change JSObject::getGroup to static method. r=jandem
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/IonCaches.cpp
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsfun.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/shell/js.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/Interpreter.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/TypeInference.cpp
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1100,24 +1100,30 @@ DenseOrUnboxedArraySetElemStubExists(JSC
                                      ICSetElem_Fallback* stub, HandleObject obj)
 {
     MOZ_ASSERT(kind == ICStub::SetElem_DenseOrUnboxedArray ||
                kind == ICStub::SetElem_DenseOrUnboxedArrayAdd);
 
     for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
         if (kind == ICStub::SetElem_DenseOrUnboxedArray && iter->isSetElem_DenseOrUnboxedArray()) {
             ICSetElem_DenseOrUnboxedArray* nstub = iter->toSetElem_DenseOrUnboxedArray();
-            if (obj->maybeShape() == nstub->shape() && obj->getGroup(cx) == nstub->group())
+            if (obj->maybeShape() == nstub->shape() &&
+                JSObject::getGroup(cx, obj) == nstub->group())
+            {
                 return true;
+            }
         }
 
         if (kind == ICStub::SetElem_DenseOrUnboxedArrayAdd && iter->isSetElem_DenseOrUnboxedArrayAdd()) {
             ICSetElem_DenseOrUnboxedArrayAdd* nstub = iter->toSetElem_DenseOrUnboxedArrayAdd();
-            if (obj->getGroup(cx) == nstub->group() && SetElemAddHasSameShapes(nstub, obj))
+            if (JSObject::getGroup(cx, obj) == nstub->group() &&
+                SetElemAddHasSameShapes(nstub, obj))
+            {
                 return true;
+            }
         }
     }
     return false;
 }
 
 static bool
 TypedArraySetElemStubExists(ICSetElem_Fallback* stub, HandleObject obj, bool expectOOB)
 {
@@ -1297,17 +1303,17 @@ DoSetElemFallback(JSContext* cx, Baselin
         bool addingCase;
         size_t protoDepth;
 
         if (CanOptimizeDenseOrUnboxedArraySetElem(obj, index.toInt32(),
                                                   oldShape, oldCapacity, oldInitLength,
                                                   &addingCase, &protoDepth))
         {
             RootedShape shape(cx, obj->maybeShape());
-            RootedObjectGroup group(cx, obj->getGroup(cx));
+            RootedObjectGroup group(cx, JSObject::getGroup(cx, obj));
             if (!group)
                 return false;
 
             if (addingCase &&
                 !DenseOrUnboxedArraySetElemStubExists(cx, ICStub::SetElem_DenseOrUnboxedArrayAdd,
                                                       stub, obj))
             {
                 JitSpew(JitSpew_BaselineIC,
@@ -2899,17 +2905,17 @@ DoSetPropFallback(JSContext* cx, Baselin
     else
         name = script->getName(pc);
     RootedId id(cx, NameToId(name));
 
     RootedObject obj(cx, ToObjectFromStack(cx, lhs));
     if (!obj)
         return false;
     RootedShape oldShape(cx, obj->maybeShape());
-    RootedObjectGroup oldGroup(cx, obj->getGroup(cx));
+    RootedObjectGroup oldGroup(cx, JSObject::getGroup(cx, obj));
     if (!oldGroup)
         return false;
     RootedReceiverGuard oldGuard(cx, ReceiverGuard(obj));
 
     if (obj->is<UnboxedPlainObject>()) {
         MOZ_ASSERT(!oldShape);
         if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
             oldShape = expando->lastProperty();
@@ -3919,24 +3925,23 @@ GetTemplateObjectForNative(JSContext* cx
         if (!TypedArrayObject::GetTemplateObjectForNative(cx, native, len, res))
             return false;
         if (res)
             return true;
     }
 
     if (native == js::array_slice) {
         if (args.thisv().isObject()) {
-            JSObject* obj = &args.thisv().toObject();
+            RootedObject obj(cx, &args.thisv().toObject());
             if (!obj->isSingleton()) {
                 if (obj->group()->maybePreliminaryObjects()) {
                     *skipAttach = true;
                     return true;
                 }
-                res.set(NewFullyAllocatedArrayTryReuseGroup(cx, &args.thisv().toObject(), 0,
-                                                            TenuredObject));
+                res.set(NewFullyAllocatedArrayTryReuseGroup(cx, obj, 0, TenuredObject));
                 if (!res)
                     return false;
                 EnsureArrayGroupAnalyzed(cx, res);
                 return true;
             }
         }
     }
 
@@ -6578,17 +6583,17 @@ ICSetElem_DenseOrUnboxedArrayAdd::ICSetE
     extra_ = protoChainDepth;
 }
 
 template <size_t ProtoChainDepth>
 ICUpdatedStub*
 ICSetElemDenseOrUnboxedArrayAddCompiler::getStubSpecific(ICStubSpace* space,
                                                          Handle<ShapeVector> shapes)
 {
-    RootedObjectGroup group(cx, obj_->getGroup(cx));
+    RootedObjectGroup group(cx, JSObject::getGroup(cx, obj_));
     if (!group)
         return nullptr;
     Rooted<JitCode*> stubCode(cx, getStubCode());
     return newStub<ICSetElem_DenseOrUnboxedArrayAddImpl<ProtoChainDepth>>(space, stubCode, group, shapes);
 }
 
 ICSetElem_TypedArray::ICSetElem_TypedArray(JitCode* stubCode, Shape* shape, Scalar::Type type,
                                            bool expectOutOfBounds)
@@ -6681,17 +6686,17 @@ ICSetProp_Native::ICSetProp_Native(JitCo
     group_(group),
     shape_(shape),
     offset_(offset)
 { }
 
 ICSetProp_Native*
 ICSetProp_Native::Compiler::getStub(ICStubSpace* space)
 {
-    RootedObjectGroup group(cx, obj_->getGroup(cx));
+    RootedObjectGroup group(cx, JSObject::getGroup(cx, obj_));
     if (!group)
         return nullptr;
 
     RootedShape shape(cx, LastPropertyForSetProp(obj_));
     ICSetProp_Native* stub = newStub<ICSetProp_Native>(space, getStubCode(), group, shape, offset_);
     if (!stub || !stub->initUpdatingChain(cx, space))
         return nullptr;
     return stub;
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -1270,17 +1270,17 @@ class ICSetPropNativeAddCompiler : publi
   public:
     ICSetPropNativeAddCompiler(JSContext* cx, HandleObject obj,
                                HandleShape oldShape, HandleObjectGroup oldGroup,
                                size_t protoChainDepth, bool isFixedSlot, uint32_t offset);
 
     template <size_t ProtoChainDepth>
     ICUpdatedStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes)
     {
-        RootedObjectGroup newGroup(cx, obj_->getGroup(cx));
+        RootedObjectGroup newGroup(cx, JSObject::getGroup(cx, obj_));
         if (!newGroup)
             return nullptr;
 
         // Only specify newGroup when the object's group changes due to the
         // object becoming fully initialized per the acquired properties
         // analysis.
         if (newGroup == oldGroup_)
             newGroup = nullptr;
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3699,17 +3699,17 @@ SetPropertyIC::update(JSContext* cx, Han
     SetPropertyIC& cache = ion->getCache(cacheIndex).toSetProperty();
 
     // Remember the old group and shape if we may attach an add-property stub.
     // Also, some code under tryAttachStub depends on obj having a non-lazy
     // group, see for instance CanInlineSetPropTypeCheck.
     RootedObjectGroup oldGroup(cx);
     RootedShape oldShape(cx);
     if (cache.canAttachStub()) {
-        oldGroup = obj->getGroup(cx);
+        oldGroup = JSObject::getGroup(cx, obj);
         if (!oldGroup)
             return false;
 
         oldShape = obj->maybeShape();
         if (obj->is<UnboxedPlainObject>()) {
             MOZ_ASSERT(!oldShape);
             if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
                 oldShape = expando->lastProperty();
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -616,17 +616,17 @@ js::ArraySetLength(JSContext* cx, Handle
         // know in case that sparse indexed element is non-configurable, as
         // that element must prevent any deletions below it.  Bug 586842 should
         // fix this inefficiency by moving indexed storage to be entirely
         // separate from non-indexed storage.
         // A second reason for this optimization to be invalid is an active
         // for..in iteration over the array. Keys deleted before being reached
         // during the iteration must not be visited, and suppressing them here
         // would be too costly.
-        ObjectGroup* arrGroup = arr->getGroup(cx);
+        ObjectGroup* arrGroup = JSObject::getGroup(cx, arr);
         if (MOZ_UNLIKELY(!arrGroup))
             return false;
         if (!arr->isIndexed() && !MOZ_UNLIKELY(arrGroup->hasAllFlags(OBJECT_FLAG_ITERATED))) {
             if (!arr->maybeCopyElementsForWrite(cx))
                 return false;
 
             uint32_t oldCapacity = arr->getDenseCapacity();
             uint32_t oldInitializedLength = arr->getDenseInitializedLength();
@@ -1319,17 +1319,17 @@ InitArrayElements(JSContext* cx, HandleO
                   uint32_t count, const Value* vector,
                   ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update)
 {
     MOZ_ASSERT(count <= MAX_ARRAY_INDEX);
 
     if (count == 0)
         return true;
 
-    ObjectGroup* group = obj->getGroup(cx);
+    ObjectGroup* group = JSObject::getGroup(cx, obj);
     if (!group)
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         DenseElementResult result =
             SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, start, vector, count, updateTypes);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
@@ -2187,17 +2187,17 @@ js::ArrayShiftMoveElements(JSObject* obj
 
 template <JSValueType Type>
 DenseElementResult
 ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
     if (ObjectMayHaveExtraIndexedProperties(obj))
         return DenseElementResult::Incomplete;
 
-    RootedObjectGroup group(cx, obj->getGroup(cx));
+    RootedObjectGroup group(cx, JSObject::getGroup(cx, obj));
     if (MOZ_UNLIKELY(!group))
         return DenseElementResult::Failure;
 
     if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED)))
         return DenseElementResult::Incomplete;
 
     size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
     if (initlen == 0)
@@ -2390,17 +2390,17 @@ CanOptimizeForDenseStorage(HandleObject 
     /*
      * Don't optimize if the array might be in the midst of iteration.  We
      * rely on this to be able to safely move dense array elements around with
      * just a memmove (see NativeObject::moveDenseArrayElements), without worrying
      * about updating any in-progress enumerators for properties implicitly
      * deleted if a hole is moved from one location to another location not yet
      * visited.  See bug 690622.
      */
-    ObjectGroup* arrGroup = arr->getGroup(cx);
+    ObjectGroup* arrGroup = JSObject::getGroup(cx, arr);
     if (!arrGroup) {
         cx->recoverFromOutOfMemory();
         return false;
     }
     if (MOZ_UNLIKELY(arrGroup->hasAllFlags(OBJECT_FLAG_ITERATED)))
         return false;
 
     /*
@@ -3628,41 +3628,41 @@ js::NewPartlyAllocatedArrayTryUseGroup(E
 // capacity and length. If possible, try to reuse the group of the input
 // object. The resulting array will either reuse the input object's group or
 // will have unknown property types. Additionally, the result will have the
 // same boxed/unboxed elements representation as the input object, unless
 // |length| is larger than the input object's initialized length (in which case
 // UnboxedArrayObject::MaximumCapacity might be exceeded).
 template <uint32_t maxLength>
 static inline JSObject*
-NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
+NewArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length,
                       NewObjectKind newKind = GenericObject)
 {
     if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>())
         return NewArray<maxLength>(cx, length, nullptr, newKind);
 
     if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype())
         return NewArray<maxLength>(cx, length, nullptr, newKind);
 
-    RootedObjectGroup group(cx, obj->getGroup(cx));
+    RootedObjectGroup group(cx, JSObject::getGroup(cx, obj));
     if (!group)
         return nullptr;
 
     return NewArrayTryUseGroup<maxLength>(cx, group, length, newKind);
 }
 
 JSObject*
-js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
+js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length,
                                         NewObjectKind newKind)
 {
     return NewArrayTryReuseGroup<UINT32_MAX>(cx, obj, length, newKind);
 }
 
 JSObject*
-js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length)
+js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length)
 {
     return NewArrayTryReuseGroup<ArrayObject::EagerAllocationMaxLength>(cx, obj, length);
 }
 
 JSObject*
 js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
                                                    NewObjectKind newKind)
 {
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -80,21 +80,21 @@ NewDenseCopyOnWriteArray(JSContext* cx, 
 extern JSObject*
 NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
                                   NewObjectKind newKind = GenericObject);
 
 extern JSObject*
 NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
 
 extern JSObject*
-NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
+NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length,
                                     NewObjectKind newKind = GenericObject);
 
 extern JSObject*
-NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
+NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length);
 
 extern JSObject*
 NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
                                                NewObjectKind newKind = GenericObject);
 
 extern JSObject*
 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -844,17 +844,17 @@ CreateFunctionPrototype(JSContext* cx, J
                                              options,
                                              sourceObject,
                                              0,
                                              ss->length()));
     if (!script || !JSScript::initFunctionPrototype(cx, script, functionProto))
         return nullptr;
 
     functionProto->initScript(script);
-    ObjectGroup* protoGroup = functionProto->getGroup(cx);
+    ObjectGroup* protoGroup = JSObject::getGroup(cx, functionProto);
     if (!protoGroup)
         return nullptr;
 
     protoGroup->setInterpretedFunction(functionProto);
 
     /*
      * The default 'new' group of Function.prototype is required by type
      * inference to have unknown properties, to simplify handling of e.g.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1502,19 +1502,19 @@ JSObject::swap(JSContext* cx, HandleObje
     MOZ_ASSERT(IsBackgroundFinalized(a->asTenured().getAllocKind()) ==
                IsBackgroundFinalized(b->asTenured().getAllocKind()));
     MOZ_ASSERT(a->compartment() == b->compartment());
 
     AutoEnterOOMUnsafeRegion oomUnsafe;
 
     AutoCompartment ac(cx, a);
 
-    if (!a->getGroup(cx))
+    if (!JSObject::getGroup(cx, a))
         oomUnsafe.crash("JSObject::swap");
-    if (!b->getGroup(cx))
+    if (!JSObject::getGroup(cx, b))
         oomUnsafe.crash("JSObject::swap");
 
     /*
      * Neither object may be in the nursery, but ensure we update any embedded
      * nursery pointers in either object.
      */
     MOZ_ASSERT(!IsInsideNursery(a) && !IsInsideNursery(b));
     cx->runtime()->gc.storeBuffer.putWholeCell(a);
@@ -3905,17 +3905,18 @@ displayAtomFromObjectGroup(ObjectGroup& 
         return nullptr;
 
     return script->function()->displayAtom();
 }
 
 bool
 JSObject::constructorDisplayAtom(JSContext* cx, js::MutableHandleAtom name)
 {
-    ObjectGroup *g = getGroup(cx);
+    RootedObject self(cx, this); // Temporary change.
+    ObjectGroup *g = JSObject::getGroup(cx, self);
     if (!g)
         return false;
 
     name.set(displayAtomFromObjectGroup(*g));
     return true;
 }
 
 JSAtom*
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -341,17 +341,17 @@ class JSObject : public js::gc::Cell
     // Marks this object as having a singleton group, and leave the group lazy.
     // Constructs a new, unique shape for the object. This should only be
     // called for an object that was just created.
     static inline bool setSingleton(js::ExclusiveContext* cx, js::HandleObject obj);
 
     // Change an existing object to have a singleton group.
     static bool changeToSingleton(JSContext* cx, js::HandleObject obj);
 
-    inline js::ObjectGroup* getGroup(JSContext* cx);
+    static inline js::ObjectGroup* getGroup(JSContext* cx, js::HandleObject obj);
 
     const js::GCPtrObjectGroup& groupFromGC() const {
         /* Direct field access for use by GC. */
         return group_;
     }
 
     /*
      * We permit proxies to dynamically compute their prototype if desired.
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -129,27 +129,26 @@ JSObject::setSingleton(js::ExclusiveCont
                                                                  obj->taggedProto());
     if (!group)
         return false;
 
     obj->group_ = group;
     return true;
 }
 
-inline js::ObjectGroup*
-JSObject::getGroup(JSContext* cx)
+/* static */ inline js::ObjectGroup*
+JSObject::getGroup(JSContext* cx, js::HandleObject obj)
 {
-    MOZ_ASSERT(cx->compartment() == compartment());
-    if (hasLazyGroup()) {
-        JS::RootedObject self(cx, this);
-        if (cx->compartment() != compartment())
+    MOZ_ASSERT(cx->compartment() == obj->compartment());
+    if (obj->hasLazyGroup()) {
+        if (cx->compartment() != obj->compartment())
             MOZ_CRASH();
-        return makeLazyGroup(cx, self);
+        return makeLazyGroup(cx, obj);
     }
-    return group_;
+    return obj->group_;
 }
 
 inline void
 JSObject::setGroup(js::ObjectGroup* group)
 {
     MOZ_RELEASE_ASSERT(group);
     MOZ_ASSERT(!isSingleton());
     group_ = group;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3467,18 +3467,18 @@ ShapeOf(JSContext* cx, unsigned argc, JS
 static bool
 GroupOf(JSContext* cx, unsigned argc, JS::Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!args.get(0).isObject()) {
         JS_ReportErrorASCII(cx, "groupOf: object expected");
         return false;
     }
-    JSObject* obj = &args[0].toObject();
-    ObjectGroup* group = obj->getGroup(cx);
+    RootedObject obj(cx, &args[0].toObject());
+    ObjectGroup* group = JSObject::getGroup(cx, obj);
     if (!group)
         return false;
     args.rval().set(JS_NumberValue(double(uintptr_t(group) >> 3)));
     return true;
 }
 
 static bool
 UnwrappedObjectsHaveSameShape(JSContext* cx, unsigned argc, JS::Value* vp)
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -336,17 +336,17 @@ ArrayBufferObject::detach(JSContext* cx,
     // When detaching a buffer with typed object views, any jitcode accessing
     // such views must be deoptimized so that detachment checks are performed.
     // This is done by setting a compartment-wide flag indicating that buffers
     // with typed object views have been detached.
     if (buffer->hasTypedObjectViews()) {
         // Make sure the global object's group has been instantiated, so the
         // flag change will be observed.
         AutoEnterOOMUnsafeRegion oomUnsafe;
-        if (!cx->global()->getGroup(cx))
+        if (!JSObject::getGroup(cx, cx->global()))
             oomUnsafe.crash("ArrayBufferObject::detach");
         MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER);
         cx->compartment()->detachedTypedObjects = 1;
     }
 
     // Update all views of the buffer to account for the buffer having been
     // detached, and clear the buffer's data and list of views.
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4660,17 +4660,18 @@ js::RunOnceScriptPrologue(JSContext* cx,
 
     if (!script->hasRunOnce()) {
         script->setHasRunOnce();
         return true;
     }
 
     // Force instantiation of the script's function's group to ensure the flag
     // is preserved in type information.
-    if (!script->functionNonDelazifying()->getGroup(cx))
+    RootedFunction fun(cx, script->functionNonDelazifying());
+    if (!JSObject::getGroup(cx, fun))
         return false;
 
     MarkObjectGroupFlags(cx, script->functionNonDelazifying(), OBJECT_FLAG_RUNONCE_INVALIDATED);
     return true;
 }
 
 unsigned
 js::GetInitDataPropAttrs(JSOp op)
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -281,22 +281,23 @@ JSObject::splicePrototype(JSContext* cx,
 
     // Windows may not appear on prototype chains.
     MOZ_ASSERT_IF(proto.isObject(), !IsWindow(proto.toObject()));
 
     if (proto.isObject() && !proto.toObject()->setDelegate(cx))
         return false;
 
     // Force type instantiation when splicing lazy group.
-    RootedObjectGroup group(cx, self->getGroup(cx));
+    RootedObjectGroup group(cx, JSObject::getGroup(cx, self));
     if (!group)
         return false;
     RootedObjectGroup protoGroup(cx, nullptr);
     if (proto.isObject()) {
-        protoGroup = proto.toObject()->getGroup(cx);
+        RootedObject protoObj(cx, proto.toObject());
+        protoGroup = JSObject::getGroup(cx, protoObj);
         if (!protoGroup)
             return false;
     }
 
     group->setClasp(clasp);
     group->setProto(proto);
     return true;
 }
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -1319,17 +1319,18 @@ void
 js::EnsureTrackPropertyTypes(JSContext* cx, JSObject* obj, jsid id)
 {
     id = IdToTypeId(id);
 
     if (obj->isSingleton()) {
         AutoEnterAnalysis enter(cx);
         if (obj->hasLazyGroup()) {
             AutoEnterOOMUnsafeRegion oomUnsafe;
-            if (!obj->getGroup(cx)) {
+            RootedObject objRoot(cx, obj);
+            if (!JSObject::getGroup(cx, objRoot)) {
                 oomUnsafe.crash("Could not allocate ObjectGroup in EnsureTrackPropertyTypes");
                 return;
             }
         }
         if (!obj->group()->unknownProperties() && !obj->group()->getProperty(cx, obj, id)) {
             MOZ_ASSERT(obj->group()->unknownProperties());
             return;
         }
@@ -1338,19 +1339,22 @@ js::EnsureTrackPropertyTypes(JSContext* 
     MOZ_ASSERT(obj->group()->unknownProperties() || TrackPropertyTypes(cx, obj, id));
 }
 
 bool
 HeapTypeSetKey::instantiate(JSContext* cx)
 {
     if (maybeTypes())
         return true;
-    if (object()->isSingleton() && !object()->singleton()->getGroup(cx)) {
-        cx->clearPendingException();
-        return false;
+    if (object()->isSingleton()) {
+        RootedObject obj(cx, object()->singleton());
+        if (!JSObject::getGroup(cx, obj)) {
+            cx->clearPendingException();
+            return false;
+        }
     }
     JSObject* obj = object()->isSingleton() ? object()->singleton() : nullptr;
     maybeTypes_ = object()->maybeGroup()->getProperty(cx, obj, id());
     return maybeTypes_ != nullptr;
 }
 
 static bool
 CheckFrozenTypeSet(JSContext* cx, TemporaryTypeSet* frozen, StackTypeSet* actual)
@@ -3173,17 +3177,17 @@ js::AddClearDefiniteGetterSetterForProto
 {
     /*
      * Ensure that if the properties named here could have a getter, setter or
      * a permanent property in any transitive prototype, the definite
      * properties get cleared from the group.
      */
     RootedObject proto(cx, group->proto().toObjectOrNull());
     while (proto) {
-        ObjectGroup* protoGroup = proto->getGroup(cx);
+        ObjectGroup* protoGroup = JSObject::getGroup(cx, proto);
         if (!protoGroup) {
             cx->recoverFromOutOfMemory();
             return false;
         }
         if (protoGroup->unknownProperties())
             return false;
         HeapTypeSet* protoTypes = protoGroup->getProperty(cx, proto, id);
         if (!protoTypes || protoTypes->nonDataProperty() || protoTypes->nonWritableProperty())