Skip to content

Commit

Permalink
[0.64] Fix ARM64 layout issues in Office (microsoft#8689)
Browse files Browse the repository at this point in the history
* 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: microsoft#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 3fb68a2.

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
microsoft#8675. We use
this flag to address microsoft#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 <dannyvv@microsoft.com>
Co-authored-by: Andrew Coates <30809111+acoates-ms@users.noreply.github.com>
  • Loading branch information
3 people committed Jun 7, 2022
1 parent 12e9bbe commit 645056a
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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"
}
94 changes: 94 additions & 0 deletions vnext/ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h
Original file line number Diff line number Diff line change
@@ -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 <math.h>
#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 <limits>
constexpr float YGUndefined = std::numeric_limits<float>::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<float>(value), YGUnitPoint};
}
inline YGValue operator"" _pt(unsigned long long value) {
return operator"" _pt(static_cast<long double>(value));
}

inline YGValue operator"" _percent(long double value) {
return YGValue{static_cast<float>(value), YGUnitPercent};
}
inline YGValue operator"" _percent(unsigned long long value) {
return operator"" _percent(static_cast<long double>(value));
}

} // namespace literals
} // namespace yoga
} // namespace facebook

#endif
6 changes: 6 additions & 0 deletions vnext/overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit 645056a

Please sign in to comment.