From 0010b58b1d8f4060b6d299b046c3f68b5c2c21af Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 20 Apr 2023 15:27:02 -0700 Subject: [PATCH] Remove BitUtils Usage in YGNode (#1250) Summary: X-link: https://github.com/facebook/yoga/pull/1250 Pull Request resolved: https://github.com/facebook/react-native/pull/36988 BitUtils functions in Yoga are like bit fields, with more steps, and more error prone (you need to work with explicit offsets which can be tricky for anything variable length). Replace usage with a bitfield struct. Eventually I'd like to remove the BitUtils functions in general. Changelog: [Internal] Reviewed By: rshest Differential Revision: D45133645 fbshipit-source-id: f2df7821305214ad3abb38727af6cd9e9d8515b4 --- .../ReactCommon/yoga/yoga/YGNode.cpp | 36 +++++------ .../ReactCommon/yoga/yoga/YGNode.h | 60 +++++++++---------- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp index b4dbf2ed98d457..0bddb89b6da372 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp @@ -8,7 +8,6 @@ #include "YGNode.h" #include #include -#include "CompactValue.h" #include "Utils.h" using namespace facebook; @@ -16,7 +15,7 @@ using facebook::yoga::detail::CompactValue; YGNode::YGNode(YGNode&& node) { context_ = node.context_; - flags = node.flags; + flags_ = node.flags_; measure_ = node.measure_; baseline_ = node.baseline_; print_ = node.print_; @@ -42,7 +41,7 @@ YGNode::YGNode(const YGNode& node, YGConfigRef config) : YGNode{node} { void YGNode::print(void* printContext) { if (print_.noContext != nullptr) { - if (facebook::yoga::detail::getBooleanData(flags, printUsesContext_)) { + if (flags_.printUsesContext) { print_.withContext(this, printContext); } else { print_.noContext(this); @@ -202,14 +201,14 @@ YGSize YGNode::measure( float height, YGMeasureMode heightMode, void* layoutContext) { - return facebook::yoga::detail::getBooleanData(flags, measureUsesContext_) + return flags_.measureUsesContext ? measure_.withContext( this, width, widthMode, height, heightMode, layoutContext) : measure_.noContext(this, width, widthMode, height, heightMode); } float YGNode::baseline(float width, float height, void* layoutContext) { - return facebook::yoga::detail::getBooleanData(flags, baselineUsesContext_) + return flags_.baselineUsesContext ? baseline_.withContext(this, width, height, layoutContext) : baseline_.noContext(this, width, height); } @@ -236,14 +235,14 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) { } void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { - facebook::yoga::detail::setBooleanData(flags, measureUsesContext_, false); + flags_.measureUsesContext = false; decltype(YGNode::measure_) m; m.noContext = measureFunc; setMeasureFunc(m); } YOGA_EXPORT void YGNode::setMeasureFunc(MeasureWithContextFn measureFunc) { - facebook::yoga::detail::setBooleanData(flags, measureUsesContext_, true); + flags_.measureUsesContext = true; decltype(YGNode::measure_) m; m.withContext = measureFunc; setMeasureFunc(m); @@ -262,10 +261,10 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) { } void YGNode::setDirty(bool isDirty) { - if (isDirty == facebook::yoga::detail::getBooleanData(flags, isDirty_)) { + if (isDirty == flags_.isDirty) { return; } - facebook::yoga::detail::setBooleanData(flags, isDirty_, isDirty); + flags_.isDirty = isDirty; if (isDirty && dirtied_) { dirtied_(this); } @@ -408,9 +407,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { return flexBasis; } if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { - return facebook::yoga::detail::getBooleanData(flags, useWebDefaults_) - ? YGValueAuto - : YGValueZero; + return flags_.useWebDefaults ? YGValueAuto : YGValueZero; } return YGValueAuto; } @@ -449,7 +446,7 @@ void YGNode::cloneChildrenIfNeeded(void* cloneContext) { } void YGNode::markDirtyAndPropagate() { - if (!facebook::yoga::detail::getBooleanData(flags, isDirty_)) { + if (!flags_.isDirty) { setDirty(true); setLayoutComputedFlexBasis(YGFloatOptional()); if (owner_) { @@ -459,7 +456,7 @@ void YGNode::markDirtyAndPropagate() { } void YGNode::markDirtyAndPropagateDownwards() { - facebook::yoga::detail::setBooleanData(flags, isDirty_, true); + flags_.isDirty = true; for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) { childNode->markDirtyAndPropagateDownwards(); }); @@ -486,13 +483,11 @@ float YGNode::resolveFlexShrink() const { if (!style_.flexShrink().isUndefined()) { return style_.flexShrink().unwrap(); } - if (!facebook::yoga::detail::getBooleanData(flags, useWebDefaults_) && - !style_.flex().isUndefined() && style_.flex().unwrap() < 0.0f) { + if (!flags_.useWebDefaults && !style_.flex().isUndefined() && + style_.flex().unwrap() < 0.0f) { return -style_.flex().unwrap(); } - return facebook::yoga::detail::getBooleanData(flags, useWebDefaults_) - ? kWebDefaultFlexShrink - : kDefaultFlexShrink; + return flags_.useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink; } bool YGNode::isNodeFlexible() { @@ -570,8 +565,7 @@ void YGNode::reset() { clearChildren(); - auto webDefaults = - facebook::yoga::detail::getBooleanData(flags, useWebDefaults_); + auto webDefaults = flags_.useWebDefaults; *this = YGNode{getConfig()}; if (webDefaults) { useWebDefaults(); diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h index e03e421444f18e..f759a8773c76f7 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h @@ -11,7 +11,6 @@ #include #include -#include "BitUtils.h" #include "CompactValue.h" #include "YGConfig.h" #include "YGLayout.h" @@ -20,6 +19,20 @@ YGConfigRef YGConfigGetDefault(); +#pragma pack(push) +#pragma pack(1) +struct YGNodeFlags { + bool hasNewLayout : 1; + bool isReferenceBaseline : 1; + bool isDirty : 1; + uint8_t nodeType : 1; + bool measureUsesContext : 1; + bool baselineUsesContext : 1; + bool printUsesContext : 1; + bool useWebDefaults : 1; +}; +#pragma pack(pop) + struct YOGA_EXPORT YGNode { using MeasureWithContextFn = YGSize (*)(YGNode*, float, YGMeasureMode, float, YGMeasureMode, void*); @@ -27,17 +40,8 @@ struct YOGA_EXPORT YGNode { using PrintWithContextFn = void (*)(YGNode*, void*); private: - static constexpr size_t hasNewLayout_ = 0; - static constexpr size_t isReferenceBaseline_ = 1; - static constexpr size_t isDirty_ = 2; - static constexpr size_t nodeType_ = 3; - static constexpr size_t measureUsesContext_ = 4; - static constexpr size_t baselineUsesContext_ = 5; - static constexpr size_t printUsesContext_ = 6; - static constexpr size_t useWebDefaults_ = 7; - void* context_ = nullptr; - uint8_t flags = 1; + YGNodeFlags flags_ = {}; uint8_t reserved_ = 0; union { YGMeasureFunc noContext; @@ -69,7 +73,7 @@ struct YOGA_EXPORT YGNode { void setBaselineFunc(decltype(baseline_)); void useWebDefaults() { - facebook::yoga::detail::setBooleanData(flags, useWebDefaults_, true); + flags_.useWebDefaults = true; style_.flexDirection() = YGFlexDirectionRow; style_.alignContent() = YGAlignStretch; } @@ -86,6 +90,8 @@ struct YOGA_EXPORT YGNode { public: YGNode() : YGNode{YGConfigGetDefault()} {} explicit YGNode(const YGConfigRef config) : config_{config} { + flags_.hasNewLayout = true; + if (config->useWebDefaults) { useWebDefaults(); } @@ -113,12 +119,10 @@ struct YOGA_EXPORT YGNode { void print(void*); - bool getHasNewLayout() const { - return facebook::yoga::detail::getBooleanData(flags, hasNewLayout_); - } + bool getHasNewLayout() const { return flags_.hasNewLayout; } YGNodeType getNodeType() const { - return facebook::yoga::detail::getEnumData(flags, nodeType_); + return static_cast(flags_.nodeType); } bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; } @@ -145,9 +149,7 @@ struct YOGA_EXPORT YGNode { uint32_t getLineIndex() const { return lineIndex_; } - bool isReferenceBaseline() { - return facebook::yoga::detail::getBooleanData(flags, isReferenceBaseline_); - } + bool isReferenceBaseline() { return flags_.isReferenceBaseline; } // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. This method will return the parent @@ -180,9 +182,7 @@ struct YOGA_EXPORT YGNode { YGConfigRef getConfig() const { return config_; } - bool isDirty() const { - return facebook::yoga::detail::getBooleanData(flags, isDirty_); - } + bool isDirty() const { return flags_.isDirty; } std::array getResolvedDimensions() const { return resolvedDimensions_; @@ -252,21 +252,20 @@ struct YOGA_EXPORT YGNode { void setPrintFunc(YGPrintFunc printFunc) { print_.noContext = printFunc; - facebook::yoga::detail::setBooleanData(flags, printUsesContext_, false); + flags_.printUsesContext = false; } void setPrintFunc(PrintWithContextFn printFunc) { print_.withContext = printFunc; - facebook::yoga::detail::setBooleanData(flags, printUsesContext_, true); + flags_.printUsesContext = true; } void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); } void setHasNewLayout(bool hasNewLayout) { - facebook::yoga::detail::setBooleanData(flags, hasNewLayout_, hasNewLayout); + flags_.hasNewLayout = hasNewLayout; } void setNodeType(YGNodeType nodeType) { - return facebook::yoga::detail::setEnumData( - flags, nodeType_, nodeType); + flags_.nodeType = static_cast(nodeType); } void setMeasureFunc(YGMeasureFunc measureFunc); @@ -276,11 +275,11 @@ struct YOGA_EXPORT YGNode { } void setBaselineFunc(YGBaselineFunc baseLineFunc) { - facebook::yoga::detail::setBooleanData(flags, baselineUsesContext_, false); + flags_.baselineUsesContext = false; baseline_.noContext = baseLineFunc; } void setBaselineFunc(BaselineWithContextFn baseLineFunc) { - facebook::yoga::detail::setBooleanData(flags, baselineUsesContext_, true); + flags_.baselineUsesContext = true; baseline_.withContext = baseLineFunc; } void setBaselineFunc(std::nullptr_t) { @@ -296,8 +295,7 @@ struct YOGA_EXPORT YGNode { void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; } void setIsReferenceBaseline(bool isReferenceBaseline) { - facebook::yoga::detail::setBooleanData( - flags, isReferenceBaseline_, isReferenceBaseline); + flags_.isReferenceBaseline = isReferenceBaseline; } void setOwner(YGNodeRef owner) { owner_ = owner; }