mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibWasm: Return canonical NaN for min/max/floor/ceil/truncate operations
Instead of returning whichever argument was NaN, return the canonical NaN instead. The spec allows the old behavior: "Following the recommendation that operators propagate NaN payloads from their operands is permitted but not required." But Chrome, Firefox and Safari do not propagate the operand payloads. Fixes 448 WPT subtests in `wasm/core`. Co-authored-by: Ali Mohammad Pur <ali.mpfard@gmail.com>
This commit is contained in:
parent
a6857a6ce1
commit
ed94381209
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/BitCast.h>
|
||||
#include <AK/BuiltinWrappers.h>
|
||||
#include <AK/Math.h>
|
||||
#include <AK/Result.h>
|
||||
#include <AK/SIMD.h>
|
||||
#include <AK/SIMDExtras.h>
|
||||
|
|
@ -395,12 +396,10 @@ struct Minimum {
|
|||
auto operator()(Lhs lhs, Rhs rhs) const
|
||||
{
|
||||
if constexpr (IsFloatingPoint<Lhs> || IsFloatingPoint<Rhs>) {
|
||||
if (isnan(lhs) || isnan(rhs)) {
|
||||
return isnan(lhs) ? lhs : rhs;
|
||||
}
|
||||
if (lhs == 0 && rhs == 0) {
|
||||
if (isnan(lhs) || isnan(rhs))
|
||||
return AK::NaN<Lhs>;
|
||||
if (lhs == 0 && rhs == 0)
|
||||
return signbit(lhs) ? lhs : rhs;
|
||||
}
|
||||
}
|
||||
return min(lhs, rhs);
|
||||
}
|
||||
|
|
@ -413,12 +412,10 @@ struct Maximum {
|
|||
auto operator()(Lhs lhs, Rhs rhs) const
|
||||
{
|
||||
if constexpr (IsFloatingPoint<Lhs> || IsFloatingPoint<Rhs>) {
|
||||
if (isnan(lhs) || isnan(rhs)) {
|
||||
return isnan(lhs) ? lhs : rhs;
|
||||
}
|
||||
if (lhs == 0 && rhs == 0) {
|
||||
if (isnan(lhs) || isnan(rhs))
|
||||
return AK::NaN<Lhs>;
|
||||
if (lhs == 0 && rhs == 0)
|
||||
return signbit(lhs) ? rhs : lhs;
|
||||
}
|
||||
}
|
||||
return max(lhs, rhs);
|
||||
}
|
||||
|
|
@ -555,6 +552,9 @@ struct Ceil {
|
|||
template<typename Lhs>
|
||||
auto operator()(Lhs lhs) const
|
||||
{
|
||||
if (isnan(lhs))
|
||||
return AK::NaN<Lhs>;
|
||||
|
||||
if constexpr (IsSame<Lhs, float>)
|
||||
return ceilf(lhs);
|
||||
else if constexpr (IsSame<Lhs, double>)
|
||||
|
|
@ -923,6 +923,9 @@ struct Floor {
|
|||
template<typename Lhs>
|
||||
auto operator()(Lhs lhs) const
|
||||
{
|
||||
if (isnan(lhs))
|
||||
return AK::NaN<Lhs>;
|
||||
|
||||
if constexpr (IsSame<Lhs, float>)
|
||||
return floorf(lhs);
|
||||
else if constexpr (IsSame<Lhs, double>)
|
||||
|
|
@ -938,6 +941,9 @@ struct Truncate {
|
|||
template<typename Lhs>
|
||||
auto operator()(Lhs lhs) const
|
||||
{
|
||||
if (isnan(lhs))
|
||||
return AK::NaN<Lhs>;
|
||||
|
||||
if constexpr (IsSame<Lhs, float>)
|
||||
return truncf(lhs);
|
||||
else if constexpr (IsSame<Lhs, double>)
|
||||
|
|
|
|||
|
|
@ -224,14 +224,16 @@ TESTJS_GLOBAL_FUNCTION(is_canonical_nan64, isCanonicalNaN64)
|
|||
|
||||
TESTJS_GLOBAL_FUNCTION(is_arithmetic_nan32, isArithmeticNaN32)
|
||||
{
|
||||
auto value = bit_cast<float>(TRY(vm.argument(0).to_u32(vm)));
|
||||
return isnan(value);
|
||||
auto const bits = TRY(vm.argument(0).to_u32(vm));
|
||||
auto const payload = bits & 0x007FFFFF;
|
||||
return (bits & 0x7F800000) == 0x7F800000 && payload >= 0x00400000;
|
||||
}
|
||||
|
||||
TESTJS_GLOBAL_FUNCTION(is_arithmetic_nan64, isArithmeticNaN64)
|
||||
{
|
||||
auto value = bit_cast<double>(TRY(vm.argument(0).to_bigint_uint64(vm)));
|
||||
return isnan(value);
|
||||
auto const bits = TRY(vm.argument(0).to_bigint_uint64(vm));
|
||||
auto const payload = bits & 0x000FFFFFFFFFFFFFULL;
|
||||
return (bits & 0x7FF0000000000000ull) == 0x7FF0000000000000ull && payload >= 0x0008000000000000ull;
|
||||
}
|
||||
|
||||
TESTJS_GLOBAL_FUNCTION(test_simd_vector, testSIMDVector)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user