Bug 886205 (part 2) - Move some function definitions from vm/ObjectImpl-inl.h to vm/ObjectImpl.h. r=terrence.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 24 Jun 2013 16:03:02 -0700
changeset 136366 205d42d1ea463d3d047692ace1344e71f138e1cd
parent 136365 dc7d6a09e42ad115839761b08c82b47fe5d20b20
child 136367 4491b40b0fe069e77eafece123ee313c7b9624a2
push id24882
push userryanvm@gmail.com
push dateTue, 25 Jun 2013 21:02:44 +0000
treeherdermozilla-central@cc80aa0c7c13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs886205
milestone25.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 886205 (part 2) - Move some function definitions from vm/ObjectImpl-inl.h to vm/ObjectImpl.h. r=terrence.
js/src/builtin/TestingFunctions.cpp
js/src/vm/Interpreter.h
js/src/vm/ObjectImpl-inl.h
js/src/vm/ObjectImpl.cpp
js/src/vm/ObjectImpl.h
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -11,16 +11,17 @@
 #include "jsfriendapi.h"
 #include "jsgc.h"
 #include "jsobj.h"
 #include "jsprf.h"
 #include "jswrapper.h"
 
 #include "ion/AsmJS.h"
 #include "vm/ForkJoin.h"
+#include "vm/Interpreter.h"
 
 #include "vm/ObjectImpl-inl.h"
 
 using namespace js;
 using namespace JS;
 
 using mozilla::ArrayLength;
 
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -388,47 +388,16 @@ class TryNoteIter
     explicit TryNoteIter(JSContext *cx, const FrameRegs &regs);
     bool done() const;
     void operator++();
     JSTryNote *operator*() const { return tn; }
 };
 
 /************************************************************************/
 
-/*
- * To really poison a set of values, using 'magic' or 'undefined' isn't good
- * enough since often these will just be ignored by buggy code (see bug 629974)
- * in debug builds and crash in release builds. Instead, we use a safe-for-crash
- * pointer.
- */
-static JS_ALWAYS_INLINE void
-Debug_SetValueRangeToCrashOnTouch(Value *beg, Value *end)
-{
-#ifdef DEBUG
-    for (Value *v = beg; v != end; ++v)
-        v->setObject(*reinterpret_cast<JSObject *>(0x42));
-#endif
-}
-
-static JS_ALWAYS_INLINE void
-Debug_SetValueRangeToCrashOnTouch(Value *vec, size_t len)
-{
-#ifdef DEBUG
-    Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
-#endif
-}
-
-static JS_ALWAYS_INLINE void
-Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
-{
-#ifdef DEBUG
-    Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
-#endif
-}
-
 bool
 Throw(JSContext *cx, HandleValue v);
 
 bool
 GetProperty(JSContext *cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
 
 bool
 GetScopeName(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp);
--- a/js/src/vm/ObjectImpl-inl.h
+++ b/js/src/vm/ObjectImpl-inl.h
@@ -11,233 +11,60 @@
 
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsproxy.h"
 
 #include "gc/Heap.h"
 #include "gc/Marking.h"
 #include "js/TemplateLib.h"
-#include "vm/Interpreter.h"
 #include "vm/ObjectImpl.h"
 
 #include "gc/Barrier-inl.h"
 
-namespace js {
-
-static MOZ_ALWAYS_INLINE void
-Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, uint32_t len)
-{
-#ifdef DEBUG
-    Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
-#endif
-}
-
-static MOZ_ALWAYS_INLINE void
-Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
-{
-#ifdef DEBUG
-    Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
-#endif
-}
-
-} // namespace js
-
 inline JSCompartment *
 js::ObjectImpl::compartment() const
 {
     return lastProperty()->base()->compartment();
 }
 
-inline js::TaggedProto
-js::ObjectImpl::getTaggedProto() const
-{
-    return TaggedProto(getProto());
-}
-
-inline js::Shape *
-js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
-{
-    return nativeLookup(cx, pid.asId());
-}
-
-inline js::Shape *
-js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
-{
-    return nativeLookup(cx, NameToId(name));
-}
-
-inline bool
-js::ObjectImpl::nativeContains(JSContext *cx, jsid id)
-{
-    return nativeLookup(cx, id) != NULL;
-}
-
-inline bool
-js::ObjectImpl::nativeContains(JSContext *cx, PropertyName *name)
-{
-    return nativeLookup(cx, name) != NULL;
-}
-
 inline bool
 js::ObjectImpl::nativeContains(JSContext *cx, Shape *shape)
 {
     return nativeLookup(cx, shape->propid()) == shape;
 }
 
-inline js::Shape *
-js::ObjectImpl::nativeLookupPure(PropertyId pid)
-{
-    return nativeLookupPure(pid.asId());
-}
-
-inline js::Shape *
-js::ObjectImpl::nativeLookupPure(PropertyName *name)
-{
-    return nativeLookupPure(NameToId(name));
-}
-
-inline bool
-js::ObjectImpl::nativeContainsPure(jsid id)
-{
-    return nativeLookupPure(id) != NULL;
-}
-
-inline bool
-js::ObjectImpl::nativeContainsPure(PropertyName *name)
-{
-    return nativeContainsPure(NameToId(name));
-}
-
 inline bool
 js::ObjectImpl::nativeContainsPure(Shape *shape)
 {
     return nativeLookupPure(shape->propid()) == shape;
 }
 
 inline bool
 js::ObjectImpl::isExtensible() const
 {
     if (this->isProxy())
         return Proxy::isExtensible(const_cast<JSObject*>(this->asObjectPtr()));
 
     // [[Extensible]] for ordinary non-proxy objects is an object flag.
     return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
 }
 
-inline uint32_t
-js::ObjectImpl::getDenseInitializedLength()
-{
-    MOZ_ASSERT(isNative());
-    return getElementsHeader()->initializedLength;
-}
-
-inline uint32_t
-js::ObjectImpl::getDenseCapacity()
-{
-    MOZ_ASSERT(isNative());
-    return getElementsHeader()->capacity;
-}
-
-inline js::HeapSlotArray
-js::ObjectImpl::getDenseElements()
-{
-    MOZ_ASSERT(isNative());
-    return HeapSlotArray(elements);
-}
-
-inline const js::Value &
-js::ObjectImpl::getDenseElement(uint32_t idx)
-{
-    MOZ_ASSERT(isNative() && idx < getDenseInitializedLength());
-    return elements[idx];
-}
-
-inline bool
-js::ObjectImpl::containsDenseElement(uint32_t idx)
-{
-    MOZ_ASSERT(isNative());
-    return idx < getDenseInitializedLength() && !elements[idx].isMagic(JS_ELEMENTS_HOLE);
-}
-
-inline void
-js::ObjectImpl::getSlotRangeUnchecked(uint32_t start, uint32_t length,
-                                      HeapSlot **fixedStart, HeapSlot **fixedEnd,
-                                      HeapSlot **slotsStart, HeapSlot **slotsEnd)
-{
-    MOZ_ASSERT(start + length >= start);
-
-    uint32_t fixed = numFixedSlots();
-    if (start < fixed) {
-        if (start + length < fixed) {
-            *fixedStart = &fixedSlots()[start];
-            *fixedEnd = &fixedSlots()[start + length];
-            *slotsStart = *slotsEnd = NULL;
-        } else {
-            uint32_t localCopy = fixed - start;
-            *fixedStart = &fixedSlots()[start];
-            *fixedEnd = &fixedSlots()[start + localCopy];
-            *slotsStart = &slots[0];
-            *slotsEnd = &slots[length - localCopy];
-        }
-    } else {
-        *fixedStart = *fixedEnd = NULL;
-        *slotsStart = &slots[start - fixed];
-        *slotsEnd = &slots[start - fixed + length];
-    }
-}
-
-inline void
-js::ObjectImpl::getSlotRange(uint32_t start, uint32_t length,
-                             HeapSlot **fixedStart, HeapSlot **fixedEnd,
-                             HeapSlot **slotsStart, HeapSlot **slotsEnd)
-{
-    MOZ_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
-    getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
-}
-
-inline void
-js::ObjectImpl::invalidateSlotRange(uint32_t start, uint32_t length)
-{
-#ifdef DEBUG
-    HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
-    getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
-    Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
-    Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
-#endif /* DEBUG */
-}
-
 inline bool
 js::ObjectImpl::isNative() const
 {
     return lastProperty()->isNative();
 }
 
 inline bool
 js::ObjectImpl::isProxy() const
 {
     return js::IsProxy(const_cast<JSObject*>(this->asObjectPtr()));
 }
 
-inline js::HeapSlot &
-js::ObjectImpl::nativeGetSlotRef(uint32_t slot)
-{
-    MOZ_ASSERT(isNative());
-    MOZ_ASSERT(slot < slotSpan());
-    return getSlotRef(slot);
-}
-
-inline const js::Value &
-js::ObjectImpl::nativeGetSlot(uint32_t slot) const
-{
-    MOZ_ASSERT(isNative());
-    MOZ_ASSERT(slot < slotSpan());
-    return getSlot(slot);
-}
-
 #ifdef DEBUG
 inline bool
 IsObjectValueInCompartment(js::Value v, JSCompartment *comp)
 {
     if (!v.isObject())
         return true;
     return v.toObject().compartment() == comp;
 }
@@ -304,60 +131,28 @@ js::ObjectImpl::slotSpan() const
 }
 
 inline uint32_t
 js::ObjectImpl::numDynamicSlots() const
 {
     return dynamicSlotsCount(numFixedSlots(), slotSpan());
 }
 
-inline JSClass *
-js::ObjectImpl::getJSClass() const
-{
-    return Jsvalify(getClass());
-}
-
-inline const js::ObjectOps *
-js::ObjectImpl::getOps() const
-{
-    return &getClass()->ops;
-}
-
 inline bool
 js::ObjectImpl::isDelegate() const
 {
     return lastProperty()->hasObjectFlag(BaseShape::DELEGATE);
 }
 
 inline bool
 js::ObjectImpl::inDictionaryMode() const
 {
     return lastProperty()->inDictionary();
 }
 
-/* static */ inline uint32_t
-js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span)
-{
-    if (span <= nfixed)
-        return 0;
-    span -= nfixed;
-    if (span <= SLOT_CAPACITY_MIN)
-        return SLOT_CAPACITY_MIN;
-
-    uint32_t slots = RoundUpPow2(span);
-    MOZ_ASSERT(slots >= span);
-    return slots;
-}
-
-inline size_t
-js::ObjectImpl::tenuredSizeOfThis() const
-{
-    return js::gc::Arena::thingSize(tenuredGetAllocKind());
-}
-
 JS_ALWAYS_INLINE JS::Zone *
 js::ObjectImpl::zone() const
 {
     JS_ASSERT(InSequentialOrExclusiveParallelSection());
     return shape_->zone();
 }
 
 /* static */ inline void
@@ -437,22 +232,9 @@ inline void
 js::ObjectImpl::setPrivateGCThing(js::gc::Cell *cell)
 {
     void **pprivate = &privateRef(numFixedSlots());
     privateWriteBarrierPre(pprivate);
     *pprivate = reinterpret_cast<void *>(cell);
     privateWriteBarrierPost(pprivate);
 }
 
-inline void
-js::ObjectImpl::setPrivateUnbarriered(void *data)
-{
-    void **pprivate = &privateRef(numFixedSlots());
-    *pprivate = data;
-}
-
-inline void
-js::ObjectImpl::initPrivate(void *data)
-{
-    privateRef(numFixedSlots()) = data;
-}
-
 #endif /* vm_ObjectImpl_inl_h */
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -11,16 +11,28 @@
 #include "jsobjinlines.h"
 
 #include "gc/Barrier-inl.h"
 #include "gc/Marking.h"
 #include "vm/ObjectImpl-inl.h"
 
 using namespace js;
 
+void
+js::ObjectImpl::assertIsNative() const
+{
+    MOZ_ASSERT(isNative());
+}
+
+void
+js::ObjectImpl::assertSlotIsWithinSpan(uint32_t slot) const
+{
+    MOZ_ASSERT(slot < slotSpan());
+}
+
 PropDesc::PropDesc()
   : pd_(UndefinedValue()),
     value_(UndefinedValue()),
     get_(UndefinedValue()),
     set_(UndefinedValue()),
     attrs(0),
     hasGet_(false),
     hasSet_(false),
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -22,16 +22,63 @@
 
 namespace js {
 
 class Debugger;
 class ObjectImpl;
 class Nursery;
 class Shape;
 
+/*
+ * To really poison a set of values, using 'magic' or 'undefined' isn't good
+ * enough since often these will just be ignored by buggy code (see bug 629974)
+ * in debug builds and crash in release builds. Instead, we use a safe-for-crash
+ * pointer.
+ */
+static JS_ALWAYS_INLINE void
+Debug_SetValueRangeToCrashOnTouch(Value *beg, Value *end)
+{
+#ifdef DEBUG
+    for (Value *v = beg; v != end; ++v)
+        v->setObject(*reinterpret_cast<JSObject *>(0x42));
+#endif
+}
+
+static JS_ALWAYS_INLINE void
+Debug_SetValueRangeToCrashOnTouch(Value *vec, size_t len)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
+#endif
+}
+
+static JS_ALWAYS_INLINE void
+Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
+#endif
+}
+
+static MOZ_ALWAYS_INLINE void
+Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, uint32_t len)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
+#endif
+}
+
+static MOZ_ALWAYS_INLINE void
+Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
+#endif
+}
+
 static inline PropertyOp
 CastAsPropertyOp(JSObject *object)
 {
     return JS_DATA_TO_FUNC_PTR(PropertyOp, object);
 }
 
 static inline StrictPropertyOp
 CastAsStrictPropertyOp(JSObject *object)
@@ -1192,21 +1239,37 @@ class ObjectImpl : public gc::Cell
 
     inline bool isExtensible() const;
 
     // Attempt to change the [[Extensible]] bit on |obj| to false.  Callers
     // must ensure that |obj| is currently extensible before calling this!
     static bool
     preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj);
 
-    inline HeapSlotArray getDenseElements();
-    inline const Value & getDenseElement(uint32_t idx);
-    inline bool containsDenseElement(uint32_t idx);
-    inline uint32_t getDenseInitializedLength();
-    inline uint32_t getDenseCapacity();
+    HeapSlotArray getDenseElements() {
+        assertIsNative();
+        return HeapSlotArray(elements);
+    }
+    const Value &getDenseElement(uint32_t idx) {
+        assertIsNative();
+        MOZ_ASSERT(idx < getDenseInitializedLength());
+        return elements[idx];
+    }
+    bool containsDenseElement(uint32_t idx) {
+        assertIsNative();
+        return idx < getDenseInitializedLength() && !elements[idx].isMagic(JS_ELEMENTS_HOLE);
+    }
+    uint32_t getDenseInitializedLength() {
+        assertIsNative();
+        return getElementsHeader()->initializedLength;
+    }
+    uint32_t getDenseCapacity() {
+        assertIsNative();
+        return getElementsHeader()->capacity;
+    }
 
     bool makeElementsSparse(JSContext *cx) {
         NEW_OBJECT_REPRESENTATION_ONLY();
 
         MOZ_NOT_REACHED("NYI");
         return false;
     }
 
@@ -1233,29 +1296,64 @@ class ObjectImpl : public gc::Cell
 
     bool toDictionaryMode(JSContext *cx);
 
   private:
     /*
      * Get internal pointers to the range of values starting at start and
      * running for length.
      */
-    inline void getSlotRangeUnchecked(uint32_t start, uint32_t length,
-                                      HeapSlot **fixedStart, HeapSlot **fixedEnd,
-                                      HeapSlot **slotsStart, HeapSlot **slotsEnd);
-    inline void getSlotRange(uint32_t start, uint32_t length,
-                             HeapSlot **fixedStart, HeapSlot **fixedEnd,
-                             HeapSlot **slotsStart, HeapSlot **slotsEnd);
+    void getSlotRangeUnchecked(uint32_t start, uint32_t length,
+                               HeapSlot **fixedStart, HeapSlot **fixedEnd,
+                               HeapSlot **slotsStart, HeapSlot **slotsEnd)
+    {
+        MOZ_ASSERT(start + length >= start);
+
+        uint32_t fixed = numFixedSlots();
+        if (start < fixed) {
+            if (start + length < fixed) {
+                *fixedStart = &fixedSlots()[start];
+                *fixedEnd = &fixedSlots()[start + length];
+                *slotsStart = *slotsEnd = NULL;
+            } else {
+                uint32_t localCopy = fixed - start;
+                *fixedStart = &fixedSlots()[start];
+                *fixedEnd = &fixedSlots()[start + localCopy];
+                *slotsStart = &slots[0];
+                *slotsEnd = &slots[length - localCopy];
+            }
+        } else {
+            *fixedStart = *fixedEnd = NULL;
+            *slotsStart = &slots[start - fixed];
+            *slotsEnd = &slots[start - fixed + length];
+        }
+    }
+
+    void getSlotRange(uint32_t start, uint32_t length,
+                      HeapSlot **fixedStart, HeapSlot **fixedEnd,
+                      HeapSlot **slotsStart, HeapSlot **slotsEnd)
+    {
+        MOZ_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
+        getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
+    }
 
   protected:
     friend struct GCMarker;
     friend class Shape;
     friend class NewObjectCache;
 
-    inline void invalidateSlotRange(uint32_t start, uint32_t count);
+    void invalidateSlotRange(uint32_t start, uint32_t length) {
+#ifdef DEBUG
+        HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
+        getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
+        Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
+        Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
+#endif /* DEBUG */
+    }
+
     void initializeSlotRange(uint32_t start, uint32_t count);
 
     /*
      * Initialize a flat array of slots to this object at a start slot.  The
      * caller must ensure that are enough slots.
      */
     void initSlotRange(uint32_t start, const Value *vector, uint32_t length);
 
@@ -1305,30 +1403,33 @@ class ObjectImpl : public gc::Cell
     }
 
     /*
      * These functions are currently public for simplicity; in the long run
      * it may make sense to make at least some of them private.
      */
 
   public:
-    inline js::TaggedProto getTaggedProto() const;
+    js::TaggedProto getTaggedProto() const {
+        return TaggedProto(getProto());
+    }
 
     Shape * lastProperty() const {
         MOZ_ASSERT(shape_);
         return shape_;
     }
 
     bool generateOwnShape(JSContext *cx, js::Shape *newShape = NULL) {
         return replaceWithNewEquivalentShape(cx, lastProperty(), newShape);
     }
 
     inline JSCompartment *compartment() const;
 
     inline bool isNative() const;
+    void assertIsNative() const;
 
     types::TypeObject *type() const {
         MOZ_ASSERT(!hasLazyType());
         return type_;
     }
 
     uint32_t numFixedSlots() const {
         return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
@@ -1342,45 +1443,66 @@ class ObjectImpl : public gc::Cell
 
     /*
      * Whether the object's type has not been constructed yet. If an object
      * might have a lazy type, use getType() below, otherwise type().
      */
     bool hasLazyType() const { return type_->lazy(); }
 
     inline uint32_t slotSpan() const;
+    void assertSlotIsWithinSpan(uint32_t slot) const;
 
     /* Compute dynamicSlotsCount() for this object. */
     inline uint32_t numDynamicSlots() const;
 
     Shape *nativeLookup(JSContext *cx, jsid id);
-    inline Shape *nativeLookup(JSContext *cx, PropertyId pid);
-    inline Shape *nativeLookup(JSContext *cx, PropertyName *name);
+    Shape *nativeLookup(JSContext *cx, PropertyId pid) {
+        return nativeLookup(cx, pid.asId());
+    }
+    Shape *nativeLookup(JSContext *cx, PropertyName *name) {
+        return nativeLookup(cx, NameToId(name));
+    }
 
-    inline bool nativeContains(JSContext *cx, jsid id);
-    inline bool nativeContains(JSContext *cx, PropertyName* name);
+    bool nativeContains(JSContext *cx, jsid id) {
+        return nativeLookup(cx, id) != NULL;
+    }
+    bool nativeContains(JSContext *cx, PropertyName* name) {
+        return nativeLookup(cx, name) != NULL;
+    }
     inline bool nativeContains(JSContext *cx, Shape* shape);
 
     /*
      * Contextless; can be called from parallel code. Returns false if the
      * operation would have been effectful.
      */
     Shape *nativeLookupPure(jsid id);
-    inline Shape *nativeLookupPure(PropertyId pid);
-    inline Shape *nativeLookupPure(PropertyName *name);
+    Shape *nativeLookupPure(PropertyId pid) {
+        return nativeLookupPure(pid.asId());
+    }
+    Shape *nativeLookupPure(PropertyName *name) {
+        return nativeLookupPure(NameToId(name));
+    }
 
-    inline bool nativeContainsPure(jsid id);
-    inline bool nativeContainsPure(PropertyName* name);
-    inline bool nativeContainsPure(Shape* shape);
+    bool nativeContainsPure(jsid id) {
+        return nativeLookupPure(id) != NULL;
+    }
+    bool nativeContainsPure(PropertyName* name) {
+        return nativeContainsPure(NameToId(name));
+    }
+    bool nativeContainsPure(Shape* shape);
 
-    inline JSClass *getJSClass() const;
-    inline bool hasClass(const Class *c) const {
+    JSClass *getJSClass() const {
+        return Jsvalify(getClass());
+    }
+    bool hasClass(const Class *c) const {
         return getClass() == c;
     }
-    inline const ObjectOps *getOps() const;
+    const ObjectOps *getOps() const {
+        return &getClass()->ops;
+    }
 
     /*
      * An object is a delegate if it is on another object's prototype or scope
      * chain, and therefore the delegate might be asked implicitly to get or
      * set a property on behalf of another object. Delegates may be accessed
      * directly too, as may any object, but only those objects linked after the
      * head of any prototype or scope chain are flagged as delegates. This
      * definition helps to optimize shape-based property cache invalidation
@@ -1420,18 +1542,26 @@ class ObjectImpl : public gc::Cell
         return getSlotAddressUnchecked(slot);
     }
 
     HeapSlot &getSlotRef(uint32_t slot) {
         MOZ_ASSERT(slotInRange(slot));
         return *getSlotAddress(slot);
     }
 
-    inline HeapSlot &nativeGetSlotRef(uint32_t slot);
-    inline const Value &nativeGetSlot(uint32_t slot) const;
+    HeapSlot &nativeGetSlotRef(uint32_t slot) {
+        assertIsNative();
+        assertSlotIsWithinSpan(slot);
+        return getSlotRef(slot);
+    }
+    const Value &nativeGetSlot(uint32_t slot) const {
+        assertIsNative();
+        assertSlotIsWithinSpan(slot);
+        return getSlot(slot);
+    }
 
     inline void setSlot(uint32_t slot, const Value &value);
     inline void setCrossCompartmentSlot(uint32_t slot, const Value &value);
     inline void initSlot(uint32_t slot, const Value &value);
     inline void initCrossCompartmentSlot(uint32_t slot, const Value &value);
     inline void initSlotUnchecked(uint32_t slot, const Value &value);
 
     /* For slots which are known to always be fixed, due to the way they are allocated. */
@@ -1450,20 +1580,32 @@ class ObjectImpl : public gc::Cell
     inline void initFixedSlot(uint32_t slot, const Value &value);
 
     /*
      * Get the number of dynamic slots to allocate to cover the properties in
      * an object with the given number of fixed slots and slot span. The slot
      * capacity is not stored explicitly, and the allocated size of the slot
      * array is kept in sync with this count.
      */
-    static inline uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span);
+    static uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span) {
+        if (span <= nfixed)
+            return 0;
+        span -= nfixed;
+        if (span <= SLOT_CAPACITY_MIN)
+            return SLOT_CAPACITY_MIN;
+
+        uint32_t slots = RoundUpPow2(span);
+        MOZ_ASSERT(slots >= span);
+        return slots;
+    }
 
     /* Memory usage functions. */
-    inline size_t tenuredSizeOfThis() const;
+    size_t tenuredSizeOfThis() const {
+        return js::gc::Arena::thingSize(tenuredGetAllocKind());
+    }
 
     /* Elements accessors. */
 
     ObjectElements * getElementsHeader() const {
         return ObjectElements::fromElements(elements);
     }
 
     ElementsHeader & elementsHeader() const {
@@ -1526,18 +1668,23 @@ class ObjectImpl : public gc::Cell
     inline bool hasPrivate() const {
         return getClass()->hasPrivate();
     }
     inline void *getPrivate() const {
         return privateRef(numFixedSlots());
     }
     inline void setPrivate(void *data);
     inline void setPrivateGCThing(gc::Cell *cell);
-    inline void setPrivateUnbarriered(void *data);
-    inline void initPrivate(void *data);
+    void setPrivateUnbarriered(void *data) {
+        void **pprivate = &privateRef(numFixedSlots());
+        *pprivate = data;
+    }
+    void initPrivate(void *data) {
+        privateRef(numFixedSlots()) = data;
+    }
 
     /* Access private data for an object with a known number of fixed slots. */
     inline void *getPrivate(uint32_t nfixed) const {
         return privateRef(nfixed);
     }
 
     /* JIT Accessors */
     static size_t offsetOfShape() { return offsetof(ObjectImpl, shape_); }