#ifndef vm_ArrayBufferViewObject_h
#define vm_ArrayBufferViewObject_h
#include "builtin/TypedObjectConstants.h"
#include "vm/ArrayBufferObject.h"
#include "vm/NativeObject.h"
#include "vm/SharedArrayObject.h"
#include "vm/SharedMem.h"
namespace js {
class ArrayBufferViewObject : public NativeObject {
public:
static constexpr size_t BUFFER_SLOT = 0;
static_assert(BUFFER_SLOT == JS_TYPEDARRAYLAYOUT_BUFFER_SLOT,
"self-hosted code with burned-in constants must get the "
"right buffer slot");
static constexpr size_t LENGTH_SLOT = 1;
static_assert(LENGTH_SLOT == JS_TYPEDARRAYLAYOUT_LENGTH_SLOT,
"self-hosted code with burned-in constants must get the "
"right length slot");
static constexpr size_t BYTEOFFSET_SLOT = 2;
static_assert(BYTEOFFSET_SLOT == JS_TYPEDARRAYLAYOUT_BYTEOFFSET_SLOT,
"self-hosted code with burned-in constants must get the "
"right byteOffset slot");
static constexpr size_t RESERVED_SLOTS = 3;
#ifdef DEBUG
static const uint8_t ZeroLengthArrayData = 0x4A;
#endif
static constexpr size_t DATA_SLOT = 3;
private:
void* dataPointerEither_() const {
return static_cast<void*>(getPrivate(DATA_SLOT));
}
public:
MOZ_MUST_USE bool init(JSContext* cx, ArrayBufferObjectMaybeShared* buffer,
uint32_t byteOffset, uint32_t length,
uint32_t bytesPerElement);
static ArrayBufferObjectMaybeShared* bufferObject(
JSContext* cx, Handle<ArrayBufferViewObject*> obj);
void notifyBufferDetached();
uint8_t* dataPointerUnshared(const JS::AutoRequireNoGC&);
void setDataPointerUnshared(uint8_t* data);
void initDataPointer(SharedMem<uint8_t*> viewData) {
initPrivate(viewData.unwrap());
}
SharedMem<void*> dataPointerShared() const {
return SharedMem<void*>::shared(dataPointerEither_());
}
SharedMem<void*> dataPointerEither() const {
if (isSharedMemory()) {
return SharedMem<void*>::shared(dataPointerEither_());
}
return SharedMem<void*>::unshared(dataPointerEither_());
}
void* dataPointerUnshared() const {
MOZ_ASSERT(!isSharedMemory());
return dataPointerEither_();
}
static Value bufferValue(const ArrayBufferViewObject* view) {
return view->getFixedSlot(BUFFER_SLOT);
}
bool hasBuffer() const { return bufferValue(this).isObject(); }
ArrayBufferObject* bufferUnshared() const {
MOZ_ASSERT(!isSharedMemory());
ArrayBufferObjectMaybeShared* obj = bufferEither();
if (!obj) {
return nullptr;
}
return &obj->as<ArrayBufferObject>();
}
SharedArrayBufferObject* bufferShared() const {
MOZ_ASSERT(isSharedMemory());
ArrayBufferObjectMaybeShared* obj = bufferEither();
if (!obj) {
return nullptr;
}
return &obj->as<SharedArrayBufferObject>();
}
ArrayBufferObjectMaybeShared* bufferEither() const {
JSObject* obj = bufferValue(this).toObjectOrNull();
if (!obj) {
return nullptr;
}
MOZ_ASSERT(isSharedMemory() ? obj->is<SharedArrayBufferObject>()
: obj->is<ArrayBufferObject>());
return &obj->as<ArrayBufferObjectMaybeShared>();
}
bool hasDetachedBuffer() const {
if (isSharedMemory()) {
return false;
}
ArrayBufferObject* buffer = bufferUnshared();
if (!buffer) {
return false;
}
return buffer->isDetached();
}
static void trace(JSTracer* trc, JSObject* obj);
};
}
template <>
bool JSObject::is<js::ArrayBufferViewObject>() const;
#endif