Bug 974415 - Add a separate API to get the number of fixed slots in an object that can be used off-main-thread r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 06 Oct 2016 15:56:15 +0200
changeset 316829 4a31e900a255260a91c2a7617d1481166b99bc98
parent 316828 4c2db6614dbe331f79300305bc452db9d09cd7ab
child 316830 b1932246b27f02d6c6db1c6b7d1a997a30a27c91
push id32932
push userphilringnalda@gmail.com
push dateFri, 07 Oct 2016 03:24:25 +0000
treeherderautoland@7affb66131bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs974415
milestone52.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 974415 - Add a separate API to get the number of fixed slots in an object that can be used off-main-thread r=jandem
js/src/jit/MacroAssembler.cpp
js/src/jsobj.cpp
js/src/vm/NativeObject.cpp
js/src/vm/NativeObject.h
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -950,17 +950,17 @@ MacroAssembler::newGCFatInlineString(Reg
 {
     allocateNonObject(result, temp, js::gc::AllocKind::FAT_INLINE_STRING, fail);
 }
 
 void
 MacroAssembler::copySlotsFromTemplate(Register obj, const NativeObject* templateObj,
                                       uint32_t start, uint32_t end)
 {
-    uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
+    uint32_t nfixed = Min(templateObj->numFixedSlotsForCompilation(), end);
     for (unsigned i = start; i < nfixed; i++)
         storeValue(templateObj->getFixedSlot(i), Address(obj, NativeObject::getFixedSlotOffset(i)));
 }
 
 void
 MacroAssembler::fillSlotsWithConstantValue(Address base, Register temp,
                                            uint32_t start, uint32_t end, const Value& v)
 {
@@ -1250,17 +1250,17 @@ MacroAssembler::initGCThing(Register obj
             // then this would need to store emptyObjectElementsShared in that case.
             MOZ_ASSERT(!ntemplate->isSharedMemory());
 
             storePtr(ImmPtr(emptyObjectElements), Address(obj, NativeObject::offsetOfElements()));
 
             initGCSlots(obj, temp, ntemplate, initContents);
 
             if (ntemplate->hasPrivate() && !ntemplate->is<TypedArrayObject>()) {
-                uint32_t nfixed = ntemplate->numFixedSlots();
+                uint32_t nfixed = ntemplate->numFixedSlotsForCompilation();
                 storePtr(ImmPtr(ntemplate->getPrivate()),
                          Address(obj, NativeObject::getPrivateDataOffset(nfixed)));
             }
         }
     } else if (templateObj->is<InlineTypedObject>()) {
         JS::AutoAssertOnGC nogc; // off-thread, so cannot GC
         size_t nbytes = templateObj->as<InlineTypedObject>().size();
         const uint8_t* memory = templateObj->as<InlineTypedObject>().inlineTypedMem(nogc);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3741,17 +3741,16 @@ JSObject::allocKindForTenure(const js::N
 
     AllocKind kind = GetGCObjectFixedSlotsKind(as<NativeObject>().numFixedSlots());
     MOZ_ASSERT(!IsBackgroundFinalized(kind));
     if (!CanBeFinalizedInBackground(kind, getClass()))
         return kind;
     return GetBackgroundAllocKind(kind);
 }
 
-
 void
 JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info)
 {
     if (is<NativeObject>() && as<NativeObject>().hasDynamicSlots())
         info->objectsMallocHeapSlots += mallocSizeOf(as<NativeObject>().slots_);
 
     if (is<NativeObject>() && as<NativeObject>().hasDynamicElements()) {
         js::ObjectElements* elements = as<NativeObject>().getElementsHeader();
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -257,16 +257,34 @@ js::NativeObject::lookup(ExclusiveContex
 Shape*
 js::NativeObject::lookupPure(jsid id)
 {
     MOZ_ASSERT(isNative());
     return Shape::searchNoHashify(lastProperty(), id);
 }
 
 uint32_t
+js::NativeObject::numFixedSlotsForCompilation() const
+{
+    // This is an alternative method for getting the number of fixed slots in an
+    // object. It requires more logic and memory accesses than numFixedSlots()
+    // but is safe to be called from the compilation thread, even if the main
+    // thread is actively mutating the VM.
+
+    // The compiler does not have access to nursery things.
+    MOZ_ASSERT(!IsInsideNursery(this));
+
+    if (this->is<ArrayObject>())
+        return 0;
+
+    gc::AllocKind kind = asTenured().getAllocKind();
+    return gc::GetGCKindSlots(kind, getClass());
+}
+
+uint32_t
 js::NativeObject::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class* clasp)
 {
     if (span <= nfixed)
         return 0;
     span -= nfixed;
 
     // Increase the slots to SLOT_CAPACITY_MIN to decrease the likelihood
     // the dynamic slots need to get increased again. ArrayObjects ignore
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -627,16 +627,17 @@ class NativeObject : public ShapedObject
 
     uint32_t numFixedSlots() const {
         return reinterpret_cast<const shadow::Object*>(this)->numFixedSlots();
     }
     uint32_t numUsedFixedSlots() const {
         uint32_t nslots = lastProperty()->slotSpan(getClass());
         return Min(nslots, numFixedSlots());
     }
+    uint32_t numFixedSlotsForCompilation() const;
 
     uint32_t slotSpan() const {
         if (inDictionaryMode())
             return lastProperty()->base()->slotSpan();
         return lastProperty()->slotSpan();
     }
 
     /* Whether a slot is at a fixed offset from this object. */