summaryrefslogtreecommitdiffstats
path: root/js/src/vm/ArrayBufferViewObject.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/ArrayBufferViewObject.h')
-rw-r--r--js/src/vm/ArrayBufferViewObject.h166
1 files changed, 166 insertions, 0 deletions
diff --git a/js/src/vm/ArrayBufferViewObject.h b/js/src/vm/ArrayBufferViewObject.h
new file mode 100644
index 0000000000..7d6a4b70bd
--- /dev/null
+++ b/js/src/vm/ArrayBufferViewObject.h
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef vm_ArrayBufferViewObject_h
+#define vm_ArrayBufferViewObject_h
+
+#include "builtin/TypedArrayConstants.h"
+#include "vm/ArrayBufferObject.h"
+#include "vm/NativeObject.h"
+#include "vm/SharedArrayObject.h"
+#include "vm/SharedMem.h"
+
+namespace js {
+
+/*
+ * ArrayBufferViewObject
+ *
+ * Common base class for all array buffer views (DataViewObject and
+ * TypedArrayObject).
+ */
+
+class ArrayBufferViewObject : public NativeObject {
+ public:
+ // Underlying (Shared)ArrayBufferObject.
+ 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");
+
+ // Slot containing length of the view in number of typed elements.
+ static constexpr size_t LENGTH_SLOT = 1;
+
+ // Offset of view within underlying (Shared)ArrayBufferObject.
+ static constexpr size_t BYTEOFFSET_SLOT = 2;
+
+ // Pointer to raw buffer memory.
+ static constexpr size_t DATA_SLOT = 3;
+
+ static constexpr size_t RESERVED_SLOTS = 4;
+
+#ifdef DEBUG
+ static const uint8_t ZeroLengthArrayData = 0x4A;
+#endif
+
+ static constexpr int bufferOffset() {
+ return NativeObject::getFixedSlotOffset(BUFFER_SLOT);
+ }
+ static constexpr int lengthOffset() {
+ return NativeObject::getFixedSlotOffset(LENGTH_SLOT);
+ }
+ static constexpr int byteOffsetOffset() {
+ return NativeObject::getFixedSlotOffset(BYTEOFFSET_SLOT);
+ }
+ static constexpr int dataOffset() {
+ return NativeObject::getFixedSlotOffset(DATA_SLOT);
+ }
+
+ private:
+ void* dataPointerEither_() const {
+ // Note, do not check whether shared or not
+ // Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
+ return maybePtrFromReservedSlot<void>(DATA_SLOT);
+ }
+
+ public:
+ [[nodiscard]] bool init(JSContext* cx, ArrayBufferObjectMaybeShared* buffer,
+ size_t byteOffset, size_t length,
+ uint32_t bytesPerElement);
+
+ static ArrayBufferObjectMaybeShared* bufferObject(
+ JSContext* cx, Handle<ArrayBufferViewObject*> obj);
+
+ void notifyBufferDetached();
+
+ void initDataPointer(SharedMem<uint8_t*> viewData) {
+ // Install a pointer to the buffer location that corresponds
+ // to offset zero within the typed array.
+ //
+ // The following unwrap is safe because the DATA_SLOT is
+ // accessed only from jitted code and from the
+ // dataPointerEither_() accessor above; in neither case does the
+ // raw pointer escape untagged into C++ code.
+ void* data = viewData.unwrap(/*safe - see above*/);
+ initReservedSlot(DATA_SLOT, PrivateValue(data));
+ }
+
+ 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_();
+ }
+
+ Value bufferValue() const { return getFixedSlot(BUFFER_SLOT); }
+ bool hasBuffer() const { return bufferValue().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().toObjectOrNull();
+ if (!obj) {
+ return nullptr;
+ }
+ MOZ_ASSERT(isSharedMemory() ? obj->is<SharedArrayBufferObject>()
+ : obj->is<ArrayBufferObject>());
+ return &obj->as<ArrayBufferObjectMaybeShared>();
+ }
+
+ bool hasDetachedBuffer() const {
+ // Shared buffers can't be detached.
+ if (isSharedMemory()) {
+ return false;
+ }
+
+ // A typed array with a null buffer has never had its buffer exposed to
+ // become detached.
+ ArrayBufferObject* buffer = bufferUnshared();
+ if (!buffer) {
+ return false;
+ }
+
+ return buffer->isDetached();
+ }
+
+ size_t byteOffset() const {
+ return size_t(getFixedSlot(BYTEOFFSET_SLOT).toPrivate());
+ }
+
+ Value byteOffsetValue() const {
+ size_t offset = byteOffset();
+ return NumberValue(offset);
+ }
+
+ static void trace(JSTracer* trc, JSObject* obj);
+};
+
+} // namespace js
+
+template <>
+bool JSObject::is<js::ArrayBufferViewObject>() const;
+
+#endif // vm_ArrayBufferViewObject_h