Bug 1753131 - Dispatch devicechange events even without an actively capturing MediaSt...
[gecko.git] / js / src / vm / ArrayBufferObject.h
blob3b28b332d914d311f0815a66be7bac39c07e22af
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/. */
7 #ifndef vm_ArrayBufferObject_h
8 #define vm_ArrayBufferObject_h
10 #include "mozilla/Maybe.h"
12 #include <tuple> // std::tuple
14 #include "builtin/TypedArrayConstants.h"
15 #include "gc/Memory.h"
16 #include "gc/ZoneAllocator.h"
17 #include "js/ArrayBuffer.h"
18 #include "js/GCHashTable.h"
19 #include "vm/JSObject.h"
20 #include "vm/Runtime.h"
21 #include "vm/SharedMem.h"
22 #include "wasm/WasmMemory.h"
24 namespace js {
26 class ArrayBufferViewObject;
27 class WasmArrayRawBuffer;
29 namespace wasm {
30 struct MemoryDesc;
31 } // namespace wasm
33 // Create a new mapping of size `mappedSize` with an initially committed prefix
34 // of size `initialCommittedSize`. Both arguments denote bytes and must be
35 // multiples of the page size, with `initialCommittedSize` <= `mappedSize`.
36 // Returns nullptr on failure.
37 void* MapBufferMemory(wasm::IndexType, size_t mappedSize,
38 size_t initialCommittedSize);
40 // Commit additional memory in an existing mapping. `dataEnd` must be the
41 // correct value for the end of the existing committed area, and `delta` must be
42 // a byte amount to grow the mapping by, and must be a multiple of the page
43 // size. Returns false on failure.
44 bool CommitBufferMemory(void* dataEnd, size_t delta);
46 // Extend an existing mapping by adding uncommited pages to it. `dataStart`
47 // must be the pointer to the start of the existing mapping, `mappedSize` the
48 // size of the existing mapping, and `newMappedSize` the size of the extended
49 // mapping (sizes in bytes), with `mappedSize` <= `newMappedSize`. Both sizes
50 // must be divisible by the page size. Returns false on failure.
51 bool ExtendBufferMapping(void* dataStart, size_t mappedSize,
52 size_t newMappedSize);
54 // Remove an existing mapping. `dataStart` must be the pointer to the start of
55 // the mapping, and `mappedSize` the size of that mapping.
56 void UnmapBufferMemory(wasm::IndexType t, void* dataStart, size_t mappedSize);
58 // Return the number of currently live mapped buffers.
59 int32_t LiveMappedBufferCount();
61 // The inheritance hierarchy for the various classes relating to typed arrays
62 // is as follows.
65 // - JSObject
66 // - TypedObject (declared in wasm/TypedObject.h)
67 // - NativeObject
68 // - ArrayBufferObjectMaybeShared
69 // - ArrayBufferObject
70 // - SharedArrayBufferObject
71 // - ArrayBufferViewObject
72 // - DataViewObject
73 // - TypedArrayObject (declared in vm/TypedArrayObject.h)
74 // - TypedArrayObjectTemplate
75 // - Int8ArrayObject
76 // - Uint8ArrayObject
77 // - ...
79 // Note that |TypedArrayObjectTemplate| is just an implementation
80 // detail that makes implementing its various subclasses easier.
82 // ArrayBufferObject and SharedArrayBufferObject are unrelated data types:
83 // the racy memory of the latter cannot substitute for the non-racy memory of
84 // the former; the non-racy memory of the former cannot be used with the
85 // atomics; the former can be detached and the latter not. Hence they have been
86 // separated completely.
88 // Most APIs will only accept ArrayBufferObject. ArrayBufferObjectMaybeShared
89 // exists as a join point to allow APIs that can take or use either, notably
90 // AsmJS.
92 // In contrast with the separation of ArrayBufferObject and
93 // SharedArrayBufferObject, the TypedArray types can map either.
95 // The possible data ownership and reference relationships with ArrayBuffers
96 // and related classes are enumerated below. These are the possible locations
97 // for typed data:
99 // (1) malloc'ed or mmap'ed data owned by an ArrayBufferObject.
100 // (2) Data allocated inline with an ArrayBufferObject.
101 // (3) Data allocated inline with a TypedArrayObject.
102 // (4) Data allocated inline with an InlineTypedObject.
104 // An ArrayBufferObject may point to any of these sources of data, except (3).
105 // All array buffer views may point to any of these sources of data, except
106 // that (3) may only be pointed to by the typed array the data is inline with.
108 // During a minor GC, (3) and (4) may move. During a compacting GC, (2), (3),
109 // and (4) may move.
111 class ArrayBufferObjectMaybeShared;
113 wasm::IndexType WasmArrayBufferIndexType(
114 const ArrayBufferObjectMaybeShared* buf);
115 wasm::Pages WasmArrayBufferPages(const ArrayBufferObjectMaybeShared* buf);
116 wasm::Pages WasmArrayBufferClampedMaxPages(
117 const ArrayBufferObjectMaybeShared* buf);
118 mozilla::Maybe<wasm::Pages> WasmArrayBufferSourceMaxPages(
119 const ArrayBufferObjectMaybeShared* buf);
120 size_t WasmArrayBufferMappedSize(const ArrayBufferObjectMaybeShared* buf);
122 class ArrayBufferObjectMaybeShared : public NativeObject {
123 public:
124 inline size_t byteLength() const;
125 inline bool isDetached() const;
126 inline SharedMem<uint8_t*> dataPointerEither();
128 // WebAssembly support:
129 // Note: the eventual goal is to remove this from ArrayBuffer and have
130 // (Shared)ArrayBuffers alias memory owned by some wasm::Memory object.
132 wasm::IndexType wasmIndexType() const {
133 return WasmArrayBufferIndexType(this);
135 wasm::Pages wasmPages() const { return WasmArrayBufferPages(this); }
136 wasm::Pages wasmClampedMaxPages() const {
137 return WasmArrayBufferClampedMaxPages(this);
139 mozilla::Maybe<wasm::Pages> wasmSourceMaxPages() const {
140 return WasmArrayBufferSourceMaxPages(this);
142 size_t wasmMappedSize() const { return WasmArrayBufferMappedSize(this); }
144 inline bool isPreparedForAsmJS() const;
145 inline bool isWasm() const;
148 using RootedArrayBufferObjectMaybeShared =
149 Rooted<ArrayBufferObjectMaybeShared*>;
150 using HandleArrayBufferObjectMaybeShared =
151 Handle<ArrayBufferObjectMaybeShared*>;
152 using MutableHandleArrayBufferObjectMaybeShared =
153 MutableHandle<ArrayBufferObjectMaybeShared*>;
156 * ArrayBufferObject
158 * This class holds the underlying raw buffer that the various ArrayBufferViews
159 * (eg DataViewObject, the TypedArrays, TypedObjects) access. It can be created
160 * explicitly and used to construct an ArrayBufferView, or can be created
161 * lazily when it is first accessed for a TypedArrayObject or TypedObject that
162 * doesn't have an explicit buffer.
164 * ArrayBufferObject (or really the underlying memory) /is not racy/: the
165 * memory is private to a single worker.
167 class ArrayBufferObject : public ArrayBufferObjectMaybeShared {
168 static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
170 public:
171 static const uint8_t DATA_SLOT = 0;
172 static const uint8_t BYTE_LENGTH_SLOT = 1;
173 static const uint8_t FIRST_VIEW_SLOT = 2;
174 static const uint8_t FLAGS_SLOT = 3;
176 static const uint8_t RESERVED_SLOTS = 4;
178 static const size_t ARRAY_BUFFER_ALIGNMENT = 8;
180 static_assert(FLAGS_SLOT == JS_ARRAYBUFFER_FLAGS_SLOT,
181 "self-hosted code with burned-in constants must get the "
182 "right flags slot");
184 static bool supportLargeBuffers;
186 static constexpr size_t MaxByteLengthForSmallBuffer = INT32_MAX;
188 // The length of an ArrayBuffer or SharedArrayBuffer can be at most
189 // INT32_MAX. Allow a larger limit on friendly 64-bit platforms if the
190 // experimental large-buffers flag is used.
191 static size_t maxBufferByteLength() {
192 #ifdef JS_64BIT
193 if (supportLargeBuffers) {
194 return size_t(8) * 1024 * 1024 * 1024; // 8 GB.
196 #endif
197 return MaxByteLengthForSmallBuffer;
200 /** The largest number of bytes that can be stored inline. */
201 static constexpr size_t MaxInlineBytes =
202 (NativeObject::MAX_FIXED_SLOTS - RESERVED_SLOTS) * sizeof(JS::Value);
204 public:
205 enum BufferKind {
206 /** Inline data kept in the repurposed slots of this ArrayBufferObject. */
207 INLINE_DATA = 0b000,
209 /* Data allocated using the SpiderMonkey allocator. */
210 MALLOCED = 0b001,
213 * No bytes are associated with this buffer. (This could be because the
214 * buffer is detached, because it's an internal, newborn buffer not yet
215 * overwritten with user-exposable semantics, or some other reason. The
216 * point is, don't read precise language semantics into this kind.)
218 NO_DATA = 0b010,
221 * User-owned memory. The associated buffer must be manually detached
222 * before the user invalidates (deallocates, reuses the storage of, &c.)
223 * the user-owned memory.
225 USER_OWNED = 0b011,
227 WASM = 0b100,
228 MAPPED = 0b101,
229 EXTERNAL = 0b110,
231 // These kind-values are currently invalid. We intend to expand valid
232 // BufferKinds in the future to either partly or fully use these values.
233 BAD1 = 0b111,
235 KIND_MASK = 0b111
238 public:
239 enum ArrayBufferFlags {
240 // The flags also store the BufferKind
241 BUFFER_KIND_MASK = BufferKind::KIND_MASK,
243 DETACHED = 0b1000,
245 // This MALLOCED, MAPPED, or EXTERNAL buffer has been prepared for asm.js
246 // and cannot henceforth be transferred/detached. (WASM, USER_OWNED, and
247 // INLINE_DATA buffers can't be prepared for asm.js -- although if an
248 // INLINE_DATA buffer is used with asm.js, it's silently rewritten into a
249 // MALLOCED buffer which *can* be prepared.)
250 FOR_ASMJS = 0b10'0000,
253 static_assert(JS_ARRAYBUFFER_DETACHED_FLAG == DETACHED,
254 "self-hosted code with burned-in constants must use the "
255 "correct DETACHED bit value");
257 protected:
258 enum class FillContents { Zero, Uninitialized };
260 template <FillContents FillType>
261 static std::tuple<ArrayBufferObject*, uint8_t*> createBufferAndData(
262 JSContext* cx, size_t nbytes, AutoSetNewObjectMetadata&,
263 JS::Handle<JSObject*> proto = nullptr);
265 public:
266 class BufferContents {
267 uint8_t* data_;
268 BufferKind kind_;
269 JS::BufferContentsFreeFunc free_;
270 void* freeUserData_;
272 friend class ArrayBufferObject;
274 BufferContents(uint8_t* data, BufferKind kind,
275 JS::BufferContentsFreeFunc freeFunc = nullptr,
276 void* freeUserData = nullptr)
277 : data_(data),
278 kind_(kind),
279 free_(freeFunc),
280 freeUserData_(freeUserData) {
281 MOZ_ASSERT((kind_ & ~KIND_MASK) == 0);
282 MOZ_ASSERT_IF(free_ || freeUserData_, kind_ == EXTERNAL);
284 // It is the caller's responsibility to ensure that the
285 // BufferContents does not outlive the data.
288 public:
289 static BufferContents createInlineData(void* data) {
290 return BufferContents(static_cast<uint8_t*>(data), INLINE_DATA);
293 static BufferContents createMalloced(void* data) {
294 return BufferContents(static_cast<uint8_t*>(data), MALLOCED);
297 static BufferContents createNoData() {
298 return BufferContents(nullptr, NO_DATA);
301 static BufferContents createUserOwned(void* data) {
302 return BufferContents(static_cast<uint8_t*>(data), USER_OWNED);
305 static BufferContents createWasm(void* data) {
306 return BufferContents(static_cast<uint8_t*>(data), WASM);
309 static BufferContents createMapped(void* data) {
310 return BufferContents(static_cast<uint8_t*>(data), MAPPED);
313 static BufferContents createExternal(void* data,
314 JS::BufferContentsFreeFunc freeFunc,
315 void* freeUserData = nullptr) {
316 return BufferContents(static_cast<uint8_t*>(data), EXTERNAL, freeFunc,
317 freeUserData);
320 static BufferContents createFailed() {
321 // There's no harm in tagging this as MALLOCED, even tho obviously it
322 // isn't. And adding an extra tag purely for this case is a complication
323 // that presently appears avoidable.
324 return BufferContents(nullptr, MALLOCED);
327 uint8_t* data() const { return data_; }
328 BufferKind kind() const { return kind_; }
329 JS::BufferContentsFreeFunc freeFunc() const { return free_; }
330 void* freeUserData() const { return freeUserData_; }
332 explicit operator bool() const { return data_ != nullptr; }
333 WasmArrayRawBuffer* wasmBuffer() const;
336 static const JSClass class_;
337 static const JSClass protoClass_;
339 static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
341 static bool fun_isView(JSContext* cx, unsigned argc, Value* vp);
343 static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
345 static bool isOriginalByteLengthGetter(Native native) {
346 return native == byteLengthGetter;
349 static ArrayBufferObject* createForContents(JSContext* cx, size_t nbytes,
350 BufferContents contents);
352 static ArrayBufferObject* copy(
353 JSContext* cx, JS::Handle<ArrayBufferObject*> unwrappedArrayBuffer);
355 static ArrayBufferObject* createZeroed(JSContext* cx, size_t nbytes,
356 HandleObject proto = nullptr);
358 // Create an ArrayBufferObject that is safely finalizable and can later be
359 // initialize()d to become a real, content-visible ArrayBufferObject.
360 static ArrayBufferObject* createEmpty(JSContext* cx);
362 // Create an ArrayBufferObject using the provided buffer and size. Assumes
363 // ownership of |buffer| even in case of failure, i.e. on failure |buffer|
364 // is deallocated.
365 static ArrayBufferObject* createFromNewRawBuffer(JSContext* cx,
366 WasmArrayRawBuffer* buffer,
367 size_t initialSize);
369 static void copyData(Handle<ArrayBufferObject*> toBuffer, size_t toIndex,
370 Handle<ArrayBufferObject*> fromBuffer, size_t fromIndex,
371 size_t count);
373 static size_t objectMoved(JSObject* obj, JSObject* old);
375 static uint8_t* stealMallocedContents(JSContext* cx,
376 Handle<ArrayBufferObject*> buffer);
378 static BufferContents extractStructuredCloneContents(
379 JSContext* cx, Handle<ArrayBufferObject*> buffer);
381 static void addSizeOfExcludingThis(JSObject* obj,
382 mozilla::MallocSizeOf mallocSizeOf,
383 JS::ClassInfo* info,
384 JS::RuntimeSizes* runtimeSizes);
386 // ArrayBufferObjects (strongly) store the first view added to them, while
387 // later views are (weakly) stored in the compartment's InnerViewTable
388 // below. Buffers usually only have one view, so this slot optimizes for
389 // the common case. Avoiding entries in the InnerViewTable saves memory and
390 // non-incrementalized sweep time.
391 JSObject* firstView();
393 bool addView(JSContext* cx, ArrayBufferViewObject* view);
395 // Detach this buffer from its original memory. (This necessarily makes
396 // views of this buffer unusable for modifying that original memory.)
397 static void detach(JSContext* cx, Handle<ArrayBufferObject*> buffer);
399 static constexpr size_t offsetOfByteLengthSlot() {
400 return getFixedSlotOffset(BYTE_LENGTH_SLOT);
402 static constexpr size_t offsetOfFlagsSlot() {
403 return getFixedSlotOffset(FLAGS_SLOT);
406 private:
407 void setFirstView(ArrayBufferViewObject* view);
409 uint8_t* inlineDataPointer() const;
411 struct FreeInfo {
412 JS::BufferContentsFreeFunc freeFunc;
413 void* freeUserData;
415 FreeInfo* freeInfo() const;
417 public:
418 uint8_t* dataPointer() const;
419 SharedMem<uint8_t*> dataPointerShared() const;
420 size_t byteLength() const;
422 BufferContents contents() const {
423 if (isExternal()) {
424 return BufferContents(dataPointer(), EXTERNAL, freeInfo()->freeFunc,
425 freeInfo()->freeUserData);
427 return BufferContents(dataPointer(), bufferKind());
429 bool hasInlineData() const { return dataPointer() == inlineDataPointer(); }
431 void releaseData(JSFreeOp* fop);
433 BufferKind bufferKind() const {
434 return BufferKind(flags() & BUFFER_KIND_MASK);
437 bool isInlineData() const { return bufferKind() == INLINE_DATA; }
438 bool isMalloced() const { return bufferKind() == MALLOCED; }
439 bool isNoData() const { return bufferKind() == NO_DATA; }
440 bool hasUserOwnedData() const { return bufferKind() == USER_OWNED; }
442 bool isWasm() const { return bufferKind() == WASM; }
443 bool isMapped() const { return bufferKind() == MAPPED; }
444 bool isExternal() const { return bufferKind() == EXTERNAL; }
446 bool isDetached() const { return flags() & DETACHED; }
447 bool isPreparedForAsmJS() const { return flags() & FOR_ASMJS; }
449 // WebAssembly support:
452 * Prepare this ArrayBuffer for use with asm.js. Returns true on success,
453 * false on failure. This function reports no errors.
455 [[nodiscard]] bool prepareForAsmJS();
457 size_t wasmMappedSize() const;
459 wasm::IndexType wasmIndexType() const;
460 wasm::Pages wasmPages() const;
461 wasm::Pages wasmClampedMaxPages() const;
462 mozilla::Maybe<wasm::Pages> wasmSourceMaxPages() const;
464 [[nodiscard]] static bool wasmGrowToPagesInPlace(
465 wasm::IndexType t, wasm::Pages newPages,
466 Handle<ArrayBufferObject*> oldBuf,
467 MutableHandle<ArrayBufferObject*> newBuf, JSContext* cx);
468 [[nodiscard]] static bool wasmMovingGrowToPages(
469 wasm::IndexType t, wasm::Pages newPages,
470 Handle<ArrayBufferObject*> oldBuf,
471 MutableHandle<ArrayBufferObject*> newBuf, JSContext* cx);
473 static void finalize(JSFreeOp* fop, JSObject* obj);
475 static BufferContents createMappedContents(int fd, size_t offset,
476 size_t length);
478 protected:
479 void setDataPointer(BufferContents contents);
480 void setByteLength(size_t length);
482 size_t associatedBytes() const;
484 uint32_t flags() const;
485 void setFlags(uint32_t flags);
487 void setIsDetached() { setFlags(flags() | DETACHED); }
488 void setIsPreparedForAsmJS() {
489 MOZ_ASSERT(!isWasm());
490 MOZ_ASSERT(!hasUserOwnedData());
491 MOZ_ASSERT(!isInlineData());
492 MOZ_ASSERT(isMalloced() || isMapped() || isExternal());
493 setFlags(flags() | FOR_ASMJS);
496 void initialize(size_t byteLength, BufferContents contents) {
497 setByteLength(byteLength);
498 setFlags(0);
499 setFirstView(nullptr);
500 setDataPointer(contents);
503 void* initializeToInlineData(size_t byteLength) {
504 void* data = inlineDataPointer();
505 initialize(byteLength, BufferContents::createInlineData(data));
506 return data;
510 using RootedArrayBufferObject = Rooted<ArrayBufferObject*>;
511 using HandleArrayBufferObject = Handle<ArrayBufferObject*>;
512 using MutableHandleArrayBufferObject = MutableHandle<ArrayBufferObject*>;
514 // Create a buffer for a wasm memory, whose type is determined by
515 // memory.indexType().
516 bool CreateWasmBuffer(JSContext* cx, const wasm::MemoryDesc& memory,
517 MutableHandleArrayBufferObjectMaybeShared buffer);
519 // Per-compartment table that manages the relationship between array buffers
520 // and the views that use their storage.
521 class InnerViewTable {
522 public:
523 using ViewVector = GCVector<UnsafeBarePtr<JSObject*>, 1, ZoneAllocPolicy>;
525 friend class ArrayBufferObject;
527 private:
528 // This key is a raw pointer and not a WeakHeapPtr because the post-barrier
529 // would hold nursery-allocated entries live unconditionally. It is a very
530 // common pattern in low-level and performance-oriented JavaScript to create
531 // hundreds or thousands of very short lived temporary views on a larger
532 // buffer; having to tenure all of these would be a catastrophic performance
533 // regression. Thus, it is vital that nursery pointers in this map not be held
534 // live. Special support is required in the minor GC, implemented in
535 // sweepAfterMinorGC.
536 using Map = GCHashMap<UnsafeBarePtr<JSObject*>, ViewVector,
537 MovableCellHasher<JSObject*>, ZoneAllocPolicy>;
539 // For all objects sharing their storage with some other view, this maps
540 // the object to the list of such views. All entries in this map are weak.
541 Map map;
543 // List of keys from innerViews where either the source or at least one
544 // target is in the nursery. The raw pointer to a JSObject is allowed here
545 // because this vector is cleared after every minor collection. Users in
546 // sweepAfterMinorCollection must be careful to use MaybeForwarded before
547 // touching these pointers.
548 Vector<JSObject*, 0, SystemAllocPolicy> nurseryKeys;
550 // Whether nurseryKeys is a complete list.
551 bool nurseryKeysValid;
553 bool addView(JSContext* cx, ArrayBufferObject* buffer, JSObject* view);
554 ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj);
555 void removeViews(ArrayBufferObject* obj);
557 public:
558 explicit InnerViewTable(Zone* zone) : map(zone), nurseryKeysValid(true) {}
560 // Remove references to dead objects in the table and update table entries
561 // to reflect moved objects.
562 bool traceWeak(JSTracer* trc);
563 void sweepAfterMinorGC(JSTracer* trc);
565 bool empty() const { return map.empty(); }
567 bool needsSweepAfterMinorGC() const {
568 return !nurseryKeys.empty() || !nurseryKeysValid;
571 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
574 template <typename Wrapper>
575 class MutableWrappedPtrOperations<InnerViewTable, Wrapper>
576 : public WrappedPtrOperations<InnerViewTable, Wrapper> {
577 InnerViewTable& table() { return static_cast<Wrapper*>(this)->get(); }
579 public:
580 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
581 return table().sizeOfExcludingThis(mallocSizeOf);
585 class WasmArrayRawBuffer {
586 wasm::IndexType indexType_;
587 wasm::Pages clampedMaxPages_;
588 mozilla::Maybe<wasm::Pages> sourceMaxPages_;
589 size_t mappedSize_; // Not including the header page
590 size_t length_;
592 protected:
593 WasmArrayRawBuffer(wasm::IndexType indexType, uint8_t* buffer,
594 wasm::Pages clampedMaxPages,
595 const mozilla::Maybe<wasm::Pages>& sourceMaxPages,
596 size_t mappedSize, size_t length)
597 : indexType_(indexType),
598 clampedMaxPages_(clampedMaxPages),
599 sourceMaxPages_(sourceMaxPages),
600 mappedSize_(mappedSize),
601 length_(length) {
602 MOZ_ASSERT(buffer == dataPointer());
605 public:
606 static WasmArrayRawBuffer* AllocateWasm(
607 wasm::IndexType indexType, wasm::Pages initialPages,
608 wasm::Pages clampedMaxPages,
609 const mozilla::Maybe<wasm::Pages>& sourceMaxPages,
610 const mozilla::Maybe<size_t>& mappedSize);
611 static void Release(void* mem);
613 uint8_t* dataPointer() {
614 uint8_t* ptr = reinterpret_cast<uint8_t*>(this);
615 return ptr + sizeof(WasmArrayRawBuffer);
618 static const WasmArrayRawBuffer* fromDataPtr(const uint8_t* dataPtr) {
619 return reinterpret_cast<const WasmArrayRawBuffer*>(
620 dataPtr - sizeof(WasmArrayRawBuffer));
623 wasm::IndexType indexType() const { return indexType_; }
625 uint8_t* basePointer() { return dataPointer() - gc::SystemPageSize(); }
627 size_t mappedSize() const { return mappedSize_; }
629 size_t byteLength() const { return length_; }
631 wasm::Pages pages() const {
632 return wasm::Pages::fromByteLengthExact(length_);
635 wasm::Pages clampedMaxPages() const { return clampedMaxPages_; }
637 mozilla::Maybe<wasm::Pages> sourceMaxPages() const { return sourceMaxPages_; }
639 [[nodiscard]] bool growToPagesInPlace(wasm::Pages newPages);
641 [[nodiscard]] bool extendMappedSize(wasm::Pages maxPages);
643 // Try and grow the mapped region of memory. Does not change current size.
644 // Does not move memory if no space to grow.
645 void tryGrowMaxPagesInPlace(wasm::Pages deltaMaxPages);
648 } // namespace js
650 template <>
651 bool JSObject::is<js::ArrayBufferObjectMaybeShared>() const;
653 #endif // vm_ArrayBufferObject_h