summaryrefslogtreecommitdiffstats
path: root/js/src/vm/TypedArrayObject.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/vm/TypedArrayObject.h
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/vm/TypedArrayObject.h')
-rw-r--r--js/src/vm/TypedArrayObject.h301
1 files changed, 301 insertions, 0 deletions
diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h
new file mode 100644
index 0000000000..93f7706a91
--- /dev/null
+++ b/js/src/vm/TypedArrayObject.h
@@ -0,0 +1,301 @@
+/* -*- 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_TypedArrayObject_h
+#define vm_TypedArrayObject_h
+
+#include "mozilla/Maybe.h"
+#include "mozilla/TextUtils.h"
+
+#include "gc/AllocKind.h"
+#include "gc/MaybeRooted.h"
+#include "js/Class.h"
+#include "js/experimental/TypedData.h" // js::detail::TypedArrayLengthSlot
+#include "js/ScalarType.h" // js::Scalar::Type
+#include "vm/ArrayBufferObject.h"
+#include "vm/ArrayBufferViewObject.h"
+#include "vm/JSObject.h"
+#include "vm/SharedArrayObject.h"
+
+namespace js {
+
+/*
+ * TypedArrayObject
+ *
+ * The non-templated base class for the specific typed implementations.
+ * This class holds all the member variables that are used by
+ * the subclasses.
+ */
+
+class TypedArrayObject : public ArrayBufferViewObject {
+ public:
+ static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
+ "bad inlined constant in TypedData.h");
+ static_assert(js::detail::TypedArrayDataSlot == DATA_SLOT,
+ "bad inlined constant in TypedData.h");
+
+ static bool sameBuffer(Handle<TypedArrayObject*> a,
+ Handle<TypedArrayObject*> b) {
+ // Inline buffers.
+ if (!a->hasBuffer() || !b->hasBuffer()) {
+ return a.get() == b.get();
+ }
+
+ // Shared buffers.
+ if (a->isSharedMemory() && b->isSharedMemory()) {
+ return a->bufferShared()->globalID() == b->bufferShared()->globalID();
+ }
+
+ return a->bufferEither() == b->bufferEither();
+ }
+
+ static const JSClass classes[Scalar::MaxTypedArrayViewType];
+ static const JSClass protoClasses[Scalar::MaxTypedArrayViewType];
+ static const JSClass sharedTypedArrayPrototypeClass;
+
+ static const JSClass* classForType(Scalar::Type type) {
+ MOZ_ASSERT(type < Scalar::MaxTypedArrayViewType);
+ return &classes[type];
+ }
+
+ static const JSClass* protoClassForType(Scalar::Type type) {
+ MOZ_ASSERT(type < Scalar::MaxTypedArrayViewType);
+ return &protoClasses[type];
+ }
+
+ static constexpr size_t FIXED_DATA_START = RESERVED_SLOTS;
+
+ // For typed arrays which can store their data inline, the array buffer
+ // object is created lazily.
+ static constexpr uint32_t INLINE_BUFFER_LIMIT =
+ (NativeObject::MAX_FIXED_SLOTS - FIXED_DATA_START) * sizeof(Value);
+
+ static inline gc::AllocKind AllocKindForLazyBuffer(size_t nbytes);
+
+ inline Scalar::Type type() const;
+ inline size_t bytesPerElement() const;
+
+ static bool ensureHasBuffer(JSContext* cx, Handle<TypedArrayObject*> tarray);
+
+ size_t byteLength() const { return length() * bytesPerElement(); }
+
+ size_t length() const {
+ return size_t(getFixedSlot(LENGTH_SLOT).toPrivate());
+ }
+
+ Value byteLengthValue() const {
+ size_t len = byteLength();
+ return NumberValue(len);
+ }
+
+ Value lengthValue() const {
+ size_t len = length();
+ return NumberValue(len);
+ }
+
+ bool hasInlineElements() const;
+ void setInlineElements();
+ uint8_t* elementsRaw() const {
+ return maybePtrFromReservedSlot<uint8_t>(DATA_SLOT);
+ }
+ uint8_t* elements() const {
+ assertZeroLengthArrayData();
+ return elementsRaw();
+ }
+
+#ifdef DEBUG
+ void assertZeroLengthArrayData() const;
+#else
+ void assertZeroLengthArrayData() const {};
+#endif
+
+ template <AllowGC allowGC>
+ bool getElement(JSContext* cx, size_t index,
+ typename MaybeRooted<Value, allowGC>::MutableHandleType val);
+ bool getElementPure(size_t index, Value* vp);
+
+ /*
+ * Copy all elements from this typed array to vp. vp must point to rooted
+ * memory.
+ */
+ static bool getElements(JSContext* cx, Handle<TypedArrayObject*> tarray,
+ Value* vp);
+
+ static bool GetTemplateObjectForNative(JSContext* cx, Native native,
+ const JS::HandleValueArray args,
+ MutableHandleObject res);
+
+ // Maximum allowed byte length for any typed array.
+ static constexpr size_t MaxByteLength = ArrayBufferObject::MaxByteLength;
+
+ static bool isOriginalLengthGetter(Native native);
+
+ static bool isOriginalByteOffsetGetter(Native native);
+
+ static bool isOriginalByteLengthGetter(Native native);
+
+ static void finalize(JS::GCContext* gcx, JSObject* obj);
+ static size_t objectMoved(JSObject* obj, JSObject* old);
+
+ /* Initialization bits */
+
+ static const JSFunctionSpec protoFunctions[];
+ static const JSPropertySpec protoAccessors[];
+ static const JSFunctionSpec staticFunctions[];
+ static const JSPropertySpec staticProperties[];
+
+ /* Accessors and functions */
+
+ static bool is(HandleValue v);
+
+ static bool set(JSContext* cx, unsigned argc, Value* vp);
+ static bool copyWithin(JSContext* cx, unsigned argc, Value* vp);
+
+ bool convertForSideEffect(JSContext* cx, HandleValue v) const;
+
+ private:
+ static bool set_impl(JSContext* cx, const CallArgs& args);
+ static bool copyWithin_impl(JSContext* cx, const CallArgs& args);
+};
+
+extern TypedArrayObject* NewTypedArrayWithTemplateAndLength(
+ JSContext* cx, HandleObject templateObj, int32_t len);
+
+extern TypedArrayObject* NewTypedArrayWithTemplateAndArray(
+ JSContext* cx, HandleObject templateObj, HandleObject array);
+
+extern TypedArrayObject* NewTypedArrayWithTemplateAndBuffer(
+ JSContext* cx, HandleObject templateObj, HandleObject arrayBuffer,
+ HandleValue byteOffset, HandleValue length);
+
+extern TypedArrayObject* NewUint8ArrayWithLength(
+ JSContext* cx, int32_t len, gc::Heap heap = gc::Heap::Default);
+
+inline bool IsTypedArrayClass(const JSClass* clasp) {
+ return &TypedArrayObject::classes[0] <= clasp &&
+ clasp < &TypedArrayObject::classes[Scalar::MaxTypedArrayViewType];
+}
+
+inline Scalar::Type GetTypedArrayClassType(const JSClass* clasp) {
+ MOZ_ASSERT(IsTypedArrayClass(clasp));
+ return static_cast<Scalar::Type>(clasp - &TypedArrayObject::classes[0]);
+}
+
+bool IsTypedArrayConstructor(const JSObject* obj);
+
+bool IsTypedArrayConstructor(HandleValue v, Scalar::Type type);
+
+JSNative TypedArrayConstructorNative(Scalar::Type type);
+
+// In WebIDL terminology, a BufferSource is either an ArrayBuffer or a typed
+// array view. In either case, extract the dataPointer/byteLength.
+bool IsBufferSource(JSObject* object, SharedMem<uint8_t*>* dataPointer,
+ size_t* byteLength);
+
+inline Scalar::Type TypedArrayObject::type() const {
+ return GetTypedArrayClassType(getClass());
+}
+
+inline size_t TypedArrayObject::bytesPerElement() const {
+ return Scalar::byteSize(type());
+}
+
+// ES2020 draft rev a5375bdad264c8aa264d9c44f57408087761069e
+// 7.1.16 CanonicalNumericIndexString
+//
+// Checks whether or not the string is a canonical numeric index string. If the
+// string is a canonical numeric index which is not representable as a uint64_t,
+// the returned index is UINT64_MAX.
+template <typename CharT>
+mozilla::Maybe<uint64_t> StringToTypedArrayIndex(mozilla::Range<const CharT> s);
+
+// A string |s| is a TypedArray index (or: canonical numeric index string) iff
+// |s| is "-0" or |SameValue(ToString(ToNumber(s)), s)| is true. So check for
+// any characters which can start the string representation of a number,
+// including "NaN" and "Infinity".
+template <typename CharT>
+inline bool CanStartTypedArrayIndex(CharT ch) {
+ return mozilla::IsAsciiDigit(ch) || ch == '-' || ch == 'N' || ch == 'I';
+}
+
+[[nodiscard]] inline mozilla::Maybe<uint64_t> ToTypedArrayIndex(jsid id) {
+ if (id.isInt()) {
+ int32_t i = id.toInt();
+ MOZ_ASSERT(i >= 0);
+ return mozilla::Some(i);
+ }
+
+ if (MOZ_UNLIKELY(!id.isString())) {
+ return mozilla::Nothing();
+ }
+
+ JS::AutoCheckCannotGC nogc;
+ JSAtom* atom = id.toAtom();
+
+ if (atom->empty() || !CanStartTypedArrayIndex(atom->latin1OrTwoByteChar(0))) {
+ return mozilla::Nothing();
+ }
+
+ if (atom->hasLatin1Chars()) {
+ mozilla::Range<const Latin1Char> chars = atom->latin1Range(nogc);
+ return StringToTypedArrayIndex(chars);
+ }
+
+ mozilla::Range<const char16_t> chars = atom->twoByteRange(nogc);
+ return StringToTypedArrayIndex(chars);
+}
+
+bool SetTypedArrayElement(JSContext* cx, Handle<TypedArrayObject*> obj,
+ uint64_t index, HandleValue v,
+ ObjectOpResult& result);
+
+/*
+ * Implements [[DefineOwnProperty]] for TypedArrays when the property
+ * key is a TypedArray index.
+ */
+bool DefineTypedArrayElement(JSContext* cx, Handle<TypedArrayObject*> obj,
+ uint64_t index, Handle<PropertyDescriptor> desc,
+ ObjectOpResult& result);
+
+// Sort a typed array in ascending order. The typed array may be wrapped, but
+// must not be detached.
+bool intrinsic_TypedArrayNativeSort(JSContext* cx, unsigned argc, Value* vp);
+
+static inline constexpr unsigned TypedArrayShift(Scalar::Type viewType) {
+ switch (viewType) {
+ case Scalar::Int8:
+ case Scalar::Uint8:
+ case Scalar::Uint8Clamped:
+ return 0;
+ case Scalar::Int16:
+ case Scalar::Uint16:
+ return 1;
+ case Scalar::Int32:
+ case Scalar::Uint32:
+ case Scalar::Float32:
+ return 2;
+ case Scalar::BigInt64:
+ case Scalar::BigUint64:
+ case Scalar::Int64:
+ case Scalar::Float64:
+ return 3;
+ default:
+ MOZ_CRASH("Unexpected array type");
+ }
+}
+
+static inline constexpr unsigned TypedArrayElemSize(Scalar::Type viewType) {
+ return 1u << TypedArrayShift(viewType);
+}
+
+} // namespace js
+
+template <>
+inline bool JSObject::is<js::TypedArrayObject>() const {
+ return js::IsTypedArrayClass(getClass());
+}
+
+#endif /* vm_TypedArrayObject_h */