From 645056a9389b5907f9dc1d535ee800e83a7b26ed Mon Sep 17 00:00:00 2001 From: Harold Pratt <38818465+htpiv@users.noreply.github.com> Date: Thu, 21 Oct 2021 15:49:34 -0700 Subject: [PATCH] [0.64] Fix ARM64 layout issues in Office (#8689) * Change the definition of YGUndefined from NAN (contra the comment in YGValue, MSVC does define NAN) to __builtin_nanf("0"), which generates a quiet NaN. The problem with NAN is that corecrt_math.h defines it as: Which *seems* fine! However, because we are compiling with /fp:precise (see: #4122 for more details), that multiplication actually happens at runtime. And, unfortunately, we're sometimes seeing MXCSR set to round down (i.e., the_MM_ROUND_DOWN flag is set)), which, combined with th SSE instructions that happen to run here (specifically, cvtpd2ps), cause NAN, and thus YGUndefined, to yield a value of 0! What happens is that cvtpd2ps, when rounding down, converts 1#.INF in double-precision not to 1#.INF in single-precision, but instead to FLT_MAX!!! And, of course, FLT_MAX*0 is 0, not qNaN. Oops. Anyways, using __builting_nanf("0") just loads 0x7FC0000 into xmm0, rather than doing any math, so, even with /fp:precise + bad rounding modes, YGUndefined is, in fact, a quiet NaN. * Revert "Change the definition of YGUndefined from NAN (contra the comment in" This reverts commit 3fb68a26949c19d3eabcc93aa8e3d27c95727575. Rather than trying to fork YGValue.h, we'll address the underlying problem by not using /fp:strict for yoga.cpp * Compiling yoga.cpp with /fp:strict causes https://github.com/microsoft/react-native-windows/issues/8675. We use this flag to address #4122, but in my manual testing, as well by inspecting the disassembly that seemed to be responsible for issue 4122, this workaround is no longer necessary. * Patch yoga to use better definition for YGUndefined * Change files Co-authored-by: dannyvv Co-authored-by: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> --- ...-d0b46459-5370-47eb-9a2c-9c46738403cb.json | 7 ++ .../yoga/yoga/YGValue.h | 94 +++++++++++++++++++ vnext/overrides.json | 6 ++ 3 files changed, 107 insertions(+) create mode 100644 change/react-native-windows-d0b46459-5370-47eb-9a2c-9c46738403cb.json create mode 100644 vnext/ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h diff --git a/change/react-native-windows-d0b46459-5370-47eb-9a2c-9c46738403cb.json b/change/react-native-windows-d0b46459-5370-47eb-9a2c-9c46738403cb.json new file mode 100644 index 00000000000..564f8267998 --- /dev/null +++ b/change/react-native-windows-d0b46459-5370-47eb-9a2c-9c46738403cb.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Change the definition of YGUndefined from NAN to __builtin_nanf(\"0\")", + "packageName": "react-native-windows", + "email": "30809111+acoates-ms@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h new file mode 100644 index 00000000000..1853ccfec71 --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include "YGEnums.h" +#include "YGMacros.h" + +#if defined(_MSC_VER) && defined(__clang__) +#define COMPILING_WITH_CLANG_ON_WINDOWS +#endif +#if defined(COMPILING_WITH_CLANG_ON_WINDOWS) +#include +constexpr float YGUndefined = std::numeric_limits::quiet_NaN(); +#else +YG_EXTERN_C_BEGIN + +#if defined(_MSC_VER) +#define YGUndefined __builtin_nanf("0") +#else +#define YGUndefined NAN +#endif + +#endif + +typedef struct YGValue { + float value; + YGUnit unit; +} YGValue; + +YOGA_EXPORT extern const YGValue YGValueAuto; +YOGA_EXPORT extern const YGValue YGValueUndefined; +YOGA_EXPORT extern const YGValue YGValueZero; + +#if !defined(COMPILING_WITH_CLANG_ON_WINDOWS) +YG_EXTERN_C_END +#endif +#undef COMPILING_WITH_CLANG_ON_WINDOWS + +#ifdef __cplusplus + +inline bool operator==(const YGValue& lhs, const YGValue& rhs) { + if (lhs.unit != rhs.unit) { + return false; + } + + switch (lhs.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return true; + case YGUnitPoint: + case YGUnitPercent: + return lhs.value == rhs.value; + } + + return false; +} + +inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} + +inline YGValue operator-(const YGValue& value) { + return {-value.value, value.unit}; +} + +namespace facebook { +namespace yoga { +namespace literals { + +inline YGValue operator"" _pt(long double value) { + return YGValue{static_cast(value), YGUnitPoint}; +} +inline YGValue operator"" _pt(unsigned long long value) { + return operator"" _pt(static_cast(value)); +} + +inline YGValue operator"" _percent(long double value) { + return YGValue{static_cast(value), YGUnitPercent}; +} +inline YGValue operator"" _percent(unsigned long long value) { + return operator"" _percent(static_cast(value)); +} + +} // namespace literals +} // namespace yoga +} // namespace facebook + +#endif diff --git a/vnext/overrides.json b/vnext/overrides.json index 0a3a2c1a941..14f0b33133b 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -74,6 +74,12 @@ "baseHash": "95a6fd14e80719f9796942ffe59dd850a56d544c", "issue": 9791 }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h", + "baseFile": "ReactCommon/yoga/yoga/YGValue.h", + "baseHash": "1beec1c755f33ebbd4ab9ec5e138cd1a3cfba3ee" + }, { "type": "patch", "file": "ReactCommon/Yoga.cpp",