diff options
Diffstat (limited to 'js/src/vm/TypedArrayObject-inl.h')
-rw-r--r-- | js/src/vm/TypedArrayObject-inl.h | 99 |
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) { |