summaryrefslogtreecommitdiffstats
path: root/js/src/vm/TypedArrayObject-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/TypedArrayObject-inl.h')
-rw-r--r--js/src/vm/TypedArrayObject-inl.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/js/src/vm/TypedArrayObject-inl.h b/js/src/vm/TypedArrayObject-inl.h
index ffb9a3c9f6..741ebe27fb 100644
--- a/js/src/vm/TypedArrayObject-inl.h
+++ b/js/src/vm/TypedArrayObject-inl.h
@@ -28,6 +28,7 @@
#include "util/Memory.h"
#include "vm/ArrayObject.h"
#include "vm/BigIntType.h"
+#include "vm/Float16.h"
#include "vm/NativeObject.h"
#include "vm/Uint8Clamped.h"
@@ -41,6 +42,68 @@ template <typename To, typename From>
inline To ConvertNumber(From src);
template <>
+inline int8_t ConvertNumber<int8_t, float16>(float16 src) {
+ return JS::ToInt8(src.toDouble());
+}
+
+template <>
+inline uint8_t ConvertNumber<uint8_t, float16>(float16 src) {
+ return JS::ToUint8(src.toDouble());
+}
+
+template <>
+inline uint8_clamped ConvertNumber<uint8_clamped, float16>(float16 src) {
+ return uint8_clamped(src.toDouble());
+}
+
+template <>
+inline float16 ConvertNumber<float16, float16>(float16 src) {
+ return src;
+}
+
+template <>
+inline int16_t ConvertNumber<int16_t, float16>(float16 src) {
+ return JS::ToInt16(src.toDouble());
+}
+
+template <>
+inline uint16_t ConvertNumber<uint16_t, float16>(float16 src) {
+ return JS::ToUint16(src.toDouble());
+}
+
+template <>
+inline int32_t ConvertNumber<int32_t, float16>(float16 src) {
+ return JS::ToInt32(src.toDouble());
+}
+
+template <>
+inline uint32_t ConvertNumber<uint32_t, float16>(float16 src) {
+ return JS::ToUint32(src.toDouble());
+}
+
+template <>
+inline int64_t ConvertNumber<int64_t, float16>(float16 src) {
+ return JS::ToInt64(src.toDouble());
+}
+
+template <>
+inline uint64_t ConvertNumber<uint64_t, float16>(float16 src) {
+ return JS::ToUint64(src.toDouble());
+}
+
+// Float16 is a bit of a special case in that it's floating point,
+// but std::is_floating_point_v doesn't know about it.
+template <>
+inline float ConvertNumber<float, float16>(float16 src) {
+ return static_cast<float>(src.toDouble());
+}
+
+template <>
+inline double ConvertNumber<double, float16>(float16 src) {
+ return src.toDouble();
+}
+
+template <>
inline int8_t ConvertNumber<int8_t, float>(float src) {
return JS::ToInt8(src);
}
@@ -56,6 +119,11 @@ inline uint8_clamped ConvertNumber<uint8_clamped, float>(float src) {
}
template <>
+inline float16 ConvertNumber<float16, float>(float src) {
+ return float16(src);
+}
+
+template <>
inline int16_t ConvertNumber<int16_t, float>(float src) {
return JS::ToInt16(src);
}
@@ -101,6 +169,11 @@ inline uint8_clamped ConvertNumber<uint8_clamped, double>(double src) {
}
template <>
+inline float16 ConvertNumber<float16, double>(double src) {
+ return float16(src);
+}
+
+template <>
inline int16_t ConvertNumber<int16_t, double>(double src) {
return JS::ToInt16(src);
}
@@ -183,6 +256,11 @@ struct TypeIDOfType<uint64_t> {
static const JSProtoKey protoKey = JSProto_BigUint64Array;
};
template <>
+struct TypeIDOfType<float16> {
+ static const Scalar::Type id = Scalar::Float16;
+ static const JSProtoKey protoKey = JSProto_Float16Array;
+};
+template <>
struct TypeIDOfType<float> {
static const Scalar::Type id = Scalar::Float32;
static const JSProtoKey protoKey = JSProto_Float32Array;
@@ -309,11 +387,25 @@ class ElementSpecific {
MOZ_ASSERT(offset <= targetLength);
MOZ_ASSERT(sourceLength <= targetLength - offset);
+ // Return early when copying no elements.
+ //
+ // Note: `SharedMem::cast` asserts the memory is properly aligned. Non-zero
+ // memory is correctly aligned, this is statically asserted below. Zero
+ // memory can have a different alignment, so we have to return early.
+ if (sourceLength == 0) {
+ return true;
+ }
+
if (TypedArrayObject::sameBuffer(target, source)) {
return setFromOverlappingTypedArray(target, targetLength, source,
sourceLength, offset);
}
+ // `malloc` returns memory at least as strictly aligned as for max_align_t
+ // and the alignment of max_align_t is a multiple of the size of `T`,
+ // so `SharedMem::cast` will be called with properly aligned memory.
+ static_assert(alignof(std::max_align_t) % sizeof(T) == 0);
+
SharedMem<T*> dest =
target->dataPointerEither().template cast<T*>() + offset;
size_t count = sourceLength;
@@ -383,6 +475,13 @@ class ElementSpecific {
}
break;
}
+ case Scalar::Float16: {
+ SharedMem<float16*> src = data.cast<float16*>();
+ for (size_t i = 0; i < count; ++i) {
+ Ops::store(dest++, ConvertNumber<T>(Ops::load(src++)));
+ }
+ break;
+ }
case Scalar::Float32: {
SharedMem<float*> src = data.cast<float*>();
for (size_t i = 0; i < count; ++i) {