Bug 1310744: Add missing assertions in NativeObject.h r?nbp draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Wed, 19 Oct 2016 19:23:33 +0200
changeset 427491 6d74ed024323f088aa7f862621a14a722306159e
parent 427483 87df57e996e3e440b43ddd98d8bd8afffe26c88b
child 427492 3028b948769f63513f03019663479cba21e86136
push id33030
push userbmo:ecoal95@gmail.com
push dateThu, 20 Oct 2016 13:02:22 +0000
reviewersnbp
bugs1310744
milestone52.0a1
Bug 1310744: Add missing assertions in NativeObject.h r?nbp MozReview-Commit-ID: BIG3aqxp0q4
js/src/vm/NativeObject-inl.h
js/src/vm/NativeObject.cpp
js/src/vm/NativeObject.h
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -115,16 +115,17 @@ NativeObject::markDenseElementsNotPacked
     MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
 }
 
 inline void
 NativeObject::ensureDenseInitializedLengthNoPackedCheck(ExclusiveContext* cx, uint32_t index,
                                                         uint32_t extra)
 {
     MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+    MOZ_ASSERT(!denseElementsAreFrozen());
 
     /*
      * Ensure that the array's contents have been initialized up to index, and
      * mark the elements through 'index + extra' as initialized in preparation
      * for a write.
      */
     MOZ_ASSERT(index + extra <= getDenseCapacity());
     uint32_t& initlen = getElementsHeader()->initializedLength;
@@ -149,16 +150,17 @@ NativeObject::ensureDenseInitializedLeng
     ensureDenseInitializedLengthNoPackedCheck(cx, index, extra);
 }
 
 DenseElementResult
 NativeObject::extendDenseElements(ExclusiveContext* cx,
                                   uint32_t requiredCapacity, uint32_t extra)
 {
     MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+    MOZ_ASSERT(!denseElementsAreFrozen());
 
     /*
      * Don't grow elements for non-extensible objects or watched objects. Dense
      * elements can be added/written with no extensible or watchpoint checks as
      * long as there is capacity for them.
      */
     if (!nonProxyIsExtensible() || watched()) {
         MOZ_ASSERT(getDenseCapacity() == 0 || (!watched() && getElementsHeader()->isFrozen()));
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -90,16 +90,17 @@ ObjectElements::MakeElementsCopyOnWrite(
     if (!obj->ensureElements(cx, obj->getDenseInitializedLength() + 1))
         return false;
 
     ObjectElements* header = obj->getElementsHeader();
 
     // Note: this method doesn't update type information to indicate that the
     // elements might be copy on write. Handling this is left to the caller.
     MOZ_ASSERT(!header->isCopyOnWrite());
+    MOZ_ASSERT(!header->isFrozen());
     header->flags |= COPY_ON_WRITE;
 
     header->ownerObject().init(obj);
     return true;
 }
 
 /* static */ bool
 ObjectElements::FreezeElements(ExclusiveContext* cx, HandleNativeObject obj)
@@ -793,16 +794,17 @@ NativeObject::goodElementsAllocationAmou
     return true;
 }
 
 bool
 NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
 {
     MOZ_ASSERT(nonProxyIsExtensible());
     MOZ_ASSERT(canHaveNonEmptyElements());
+    MOZ_ASSERT(!denseElementsAreFrozen());
     if (denseElementsAreCopyOnWrite())
         MOZ_CRASH();
 
     uint32_t oldCapacity = getDenseCapacity();
     MOZ_ASSERT(oldCapacity < reqCapacity);
 
     uint32_t newAllocated = 0;
     if (is<ArrayObject>() && !as<ArrayObject>().lengthIsWritable()) {
@@ -887,16 +889,17 @@ NativeObject::shrinkElements(ExclusiveCo
     newheader->capacity = newCapacity;
     elements_ = newheader->elements();
 }
 
 /* static */ bool
 NativeObject::CopyElementsForWrite(ExclusiveContext* cx, NativeObject* obj)
 {
     MOZ_ASSERT(obj->denseElementsAreCopyOnWrite());
+    MOZ_ASSERT(!obj->denseElementsAreFrozen());
 
     // The original owner of a COW elements array should never be modified.
     MOZ_ASSERT(obj->getElementsHeader()->ownerObject() != obj);
 
     uint32_t initlen = obj->getDenseInitializedLength();
     uint32_t newAllocated = 0;
     if (!goodElementsAllocationAmount(cx, initlen, 0, &newAllocated))
         return false;
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -873,16 +873,17 @@ class NativeObject : public ShapedObject
     void prepareSlotRangeForOverwrite(size_t start, size_t end) {
         for (size_t i = start; i < end; i++)
             getSlotAddressUnchecked(i)->HeapSlot::~HeapSlot();
     }
 
     void prepareElementRangeForOverwrite(size_t start, size_t end) {
         MOZ_ASSERT(end <= getDenseInitializedLength());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         for (size_t i = start; i < end; i++)
             elements_[i].HeapSlot::~HeapSlot();
     }
 
     static bool rollbackProperties(ExclusiveContext* cx, HandleNativeObject obj,
                                    uint32_t slotSpan);
 
     inline void setSlotWithType(ExclusiveContext* cx, Shape* shape,
@@ -968,16 +969,17 @@ class NativeObject : public ShapedObject
 
     ObjectElements * getElementsHeader() const {
         return ObjectElements::fromElements(elements_);
     }
 
     /* Accessors for elements. */
     bool ensureElements(ExclusiveContext* cx, uint32_t capacity) {
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         if (capacity > getDenseCapacity())
             return growElements(cx, capacity);
         return true;
     }
 
     static bool goodElementsAllocationAmount(ExclusiveContext* cx, uint32_t reqAllocated,
                                              uint32_t length, uint32_t* goodAmount);
     bool growElements(ExclusiveContext* cx, uint32_t newcap);
@@ -1013,31 +1015,34 @@ class NativeObject : public ShapedObject
             }
         }
     }
 
   public:
     void setDenseInitializedLength(uint32_t length) {
         MOZ_ASSERT(length <= getDenseCapacity());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
         getElementsHeader()->initializedLength = length;
     }
 
     inline void ensureDenseInitializedLength(ExclusiveContext* cx,
                                              uint32_t index, uint32_t extra);
     void setDenseElement(uint32_t index, const Value& val) {
         MOZ_ASSERT(index < getDenseInitializedLength());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         elements_[index].set(this, HeapSlot::Element, index, val);
     }
 
     void initDenseElement(uint32_t index, const Value& val) {
         MOZ_ASSERT(index < getDenseInitializedLength());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         elements_[index].init(this, HeapSlot::Element, index, val);
     }
 
     void setDenseElementMaybeConvertDouble(uint32_t index, const Value& val) {
         if (val.isInt32() && shouldConvertDoubleElements())
             setDenseElement(index, DoubleValue(val.toInt32()));
         else
             setDenseElement(index, val);
@@ -1051,36 +1056,39 @@ class NativeObject : public ShapedObject
     static inline void removeDenseElementForSparseIndex(ExclusiveContext* cx,
                                                         HandleNativeObject obj, uint32_t index);
 
     inline Value getDenseOrTypedArrayElement(uint32_t idx);
 
     void copyDenseElements(uint32_t dstStart, const Value* src, uint32_t count) {
         MOZ_ASSERT(dstStart + count <= getDenseCapacity());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         if (JS::shadow::Zone::asShadowZone(zone())->needsIncrementalBarrier()) {
             for (uint32_t i = 0; i < count; ++i)
                 elements_[dstStart + i].set(this, HeapSlot::Element, dstStart + i, src[i]);
         } else {
             memcpy(&elements_[dstStart], src, count * sizeof(HeapSlot));
             elementsRangeWriteBarrierPost(dstStart, count);
         }
     }
 
     void initDenseElements(uint32_t dstStart, const Value* src, uint32_t count) {
         MOZ_ASSERT(dstStart + count <= getDenseCapacity());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
         memcpy(&elements_[dstStart], src, count * sizeof(HeapSlot));
         elementsRangeWriteBarrierPost(dstStart, count);
     }
 
     void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count) {
         MOZ_ASSERT(dstStart + count <= getDenseCapacity());
         MOZ_ASSERT(srcStart + count <= getDenseInitializedLength());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
 
         /*
          * Using memmove here would skip write barriers. Also, we need to consider
          * an array containing [A, B, C], in the following situation:
          *
          * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code.
          * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C].
          * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C).
@@ -1108,16 +1116,17 @@ class NativeObject : public ShapedObject
     }
 
     void moveDenseElementsNoPreBarrier(uint32_t dstStart, uint32_t srcStart, uint32_t count) {
         MOZ_ASSERT(!shadowZone()->needsIncrementalBarrier());
 
         MOZ_ASSERT(dstStart + count <= getDenseCapacity());
         MOZ_ASSERT(srcStart + count <= getDenseCapacity());
         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+        MOZ_ASSERT(!denseElementsAreFrozen());
 
         memmove(elements_ + dstStart, elements_ + srcStart, count * sizeof(Value));
         elementsRangeWriteBarrierPost(dstStart, count);
     }
 
     bool shouldConvertDoubleElements() {
         return getElementsHeader()->shouldConvertDoubleElements();
     }