ArrayObject.h (3195B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_ArrayObject_h 8 #define vm_ArrayObject_h 9 10 #include "vm/JSContext.h" 11 #include "vm/NativeObject.h" 12 13 namespace js { 14 15 class AutoSetNewObjectMetadata; 16 17 class ArrayObject : public NativeObject { 18 public: 19 // Array(x) eagerly allocates dense elements if x <= this value. 20 // This number was chosen so that the elements, the elements header, 21 // and the MediumBuffer header all fit within MaxMediumAllocSize. 22 static const uint32_t EagerAllocationMaxLength = 23 (1 << 16) - ObjectElements::VALUES_PER_HEADER - 1; 24 25 static const JSClass class_; 26 27 bool lengthIsWritable() const { 28 return !getElementsHeader()->hasNonwritableArrayLength(); 29 } 30 31 uint32_t length() const { return getElementsHeader()->length; } 32 33 void setNonWritableLength(JSContext* cx) { 34 shrinkCapacityToInitializedLength(cx); 35 assertInt32LengthFuse(cx); 36 getElementsHeader()->setNonwritableArrayLength(); 37 } 38 39 void setLengthToInitializedLength() { 40 MOZ_ASSERT(lengthIsWritable()); 41 MOZ_ASSERT_IF(length() != getElementsHeader()->length, 42 !denseElementsAreFrozen()); 43 getElementsHeader()->length = getDenseInitializedLength(); 44 static_assert(MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX, 45 "No need to check HasSeenArrayExceedsInt32LengthFuse"); 46 } 47 48 void setLength(JSContext* cx, uint32_t length) { 49 MOZ_ASSERT(lengthIsWritable()); 50 MOZ_ASSERT_IF(length != getElementsHeader()->length, 51 !denseElementsAreFrozen()); 52 assertInt32LengthFuse(cx); 53 NativeObject::elementsSizeMustNotOverflow(); 54 if (MOZ_UNLIKELY(length > INT32_MAX)) { 55 cx->runtime() 56 ->runtimeFuses.ref() 57 .hasSeenArrayExceedsInt32LengthFuse.popFuse(cx); 58 } 59 getElementsHeader()->length = length; 60 } 61 62 void assertInt32LengthFuse(JSContext* cx) { 63 MOZ_ASSERT_IF(length() > INT32_MAX, 64 !cx->runtime() 65 ->runtimeFuses.ref() 66 .hasSeenArrayExceedsInt32LengthFuse.intact()); 67 } 68 69 // Try to add a new dense element to this array. The array must be extensible. 70 // 71 // Returns DenseElementResult::Incomplete if `index >= length`, if the array 72 // has sparse elements, if we're adding a sparse element, or if the array 73 // already contains a dense element at this index. 74 inline DenseElementResult addDenseElementNoLengthChange(JSContext* cx, 75 uint32_t index, 76 const Value& val); 77 78 // Make an array object with the specified initial state. 79 static MOZ_ALWAYS_INLINE ArrayObject* create( 80 JSContext* cx, gc::AllocKind kind, gc::Heap heap, 81 Handle<SharedShape*> shape, uint32_t length, uint32_t slotSpan, 82 AutoSetNewObjectMetadata& metadata, gc::AllocSite* site = nullptr); 83 }; 84 85 } // namespace js 86 87 #endif // vm_ArrayObject_h