Simplify bitfields (#1393)

Summary:
X-link: https://github.com/facebook/react-native/pull/39485

Pull Request resolved: https://github.com/facebook/yoga/pull/1393

These were previously packed into structs to allow zero initializing all the flags at once without needing a ctor. C++ 20 has in-class member initializer support for bitfields, which makes these look more like normal member variables.

Setting enum values is a bit jank right now, due to relying on C enums which are effectively int32_t, along with GCC `-Wconversion` being a bit aggressive in needing to explicitly mask. I have some ideas to fix this later (e.g. using scoped enums internally).

bypass-github-export-checks

Changelog:
[General][Breaking] - Require C++ 20 when including renderer headers

Reviewed By: sammy-SC

Differential Revision: D49265967

fbshipit-source-id: 6ab935a866196df06e742c821f3af88eb4d18e1a
This commit is contained in:
Nick Gerleman
2023-09-19 01:28:35 -07:00
committed by Facebook GitHub Bot
parent 557d2a76fe
commit ea3869fe9f
5 changed files with 32 additions and 51 deletions

View File

@@ -25,19 +25,19 @@ Config::Config(YGLogger logger) : cloneNodeCallback_{nullptr} {
} }
void Config::setUseWebDefaults(bool useWebDefaults) { void Config::setUseWebDefaults(bool useWebDefaults) {
flags_.useWebDefaults = useWebDefaults; useWebDefaults_ = useWebDefaults;
} }
bool Config::useWebDefaults() const { bool Config::useWebDefaults() const {
return flags_.useWebDefaults; return useWebDefaults_;
} }
void Config::setShouldPrintTree(bool printTree) { void Config::setShouldPrintTree(bool printTree) {
flags_.printTree = printTree; printTree_ = printTree;
} }
bool Config::shouldPrintTree() const { bool Config::shouldPrintTree() const {
return flags_.printTree; return printTree_;
} }
void Config::setExperimentalFeatureEnabled( void Config::setExperimentalFeatureEnabled(

View File

@@ -30,15 +30,6 @@ bool configUpdateInvalidatesLayout(
const Config& oldConfig, const Config& oldConfig,
const Config& newConfig); const Config& newConfig);
#pragma pack(push)
#pragma pack(1)
// Packed structure of <32-bit options to miminize size per node.
struct ConfigFlags {
bool useWebDefaults : 1;
bool printTree : 1;
};
#pragma pack(pop)
class YG_EXPORT Config : public ::YGConfig { class YG_EXPORT Config : public ::YGConfig {
public: public:
Config(YGLogger logger); Config(YGLogger logger);
@@ -82,7 +73,9 @@ class YG_EXPORT Config : public ::YGConfig {
YGCloneNodeFunc cloneNodeCallback_; YGCloneNodeFunc cloneNodeCallback_;
YGLogger logger_; YGLogger logger_;
ConfigFlags flags_{}; bool useWebDefaults_ : 1 = false;
bool printTree_ : 1 = false;
ExperimentalFeatureSet experimentalFeatures_{}; ExperimentalFeatureSet experimentalFeatures_{};
Errata errata_ = Errata::None; Errata errata_ = Errata::None;
float pointScaleFactor_ = 1.0f; float pointScaleFactor_ = 1.0f;

View File

@@ -15,14 +15,6 @@
namespace facebook::yoga { namespace facebook::yoga {
#pragma pack(push)
#pragma pack(1)
struct LayoutResultFlags {
uint32_t direction : 2;
bool hadOverflow : 1;
};
#pragma pack(pop)
struct LayoutResults { struct LayoutResults {
// This value was chosen based on empirical data: // This value was chosen based on empirical data:
// 98% of analyzed layouts require less than 8 entries. // 98% of analyzed layouts require less than 8 entries.
@@ -35,7 +27,8 @@ struct LayoutResults {
std::array<float, 4> padding = {}; std::array<float, 4> padding = {};
private: private:
LayoutResultFlags flags_{}; uint32_t direction_ : 2 = static_cast<uint32_t>(YGDirectionInherit) & 0x03;
bool hadOverflow_ : 1 = false;
public: public:
uint32_t computedFlexBasisGeneration = 0; uint32_t computedFlexBasisGeneration = 0;
@@ -53,18 +46,18 @@ struct LayoutResults {
CachedMeasurement cachedLayout{}; CachedMeasurement cachedLayout{};
YGDirection direction() const { YGDirection direction() const {
return static_cast<YGDirection>(flags_.direction); return static_cast<YGDirection>(direction_);
} }
void setDirection(YGDirection direction) { void setDirection(YGDirection direction) {
flags_.direction = static_cast<uint32_t>(direction) & 0x03; direction_ = static_cast<uint32_t>(direction) & 0x03;
} }
bool hadOverflow() const { bool hadOverflow() const {
return flags_.hadOverflow; return hadOverflow_;
} }
void setHadOverflow(bool hadOverflow) { void setHadOverflow(bool hadOverflow) {
flags_.hadOverflow = hadOverflow; hadOverflow_ = hadOverflow;
} }
bool operator==(LayoutResults layout) const; bool operator==(LayoutResults layout) const;

View File

@@ -23,15 +23,17 @@ Node::Node(const yoga::Config* config) : config_{config} {
yoga::assertFatal( yoga::assertFatal(
config != nullptr, "Attempting to construct Node with null config"); config != nullptr, "Attempting to construct Node with null config");
flags_.hasNewLayout = true;
if (config->useWebDefaults()) { if (config->useWebDefaults()) {
useWebDefaults(); useWebDefaults();
} }
} }
Node::Node(Node&& node) { Node::Node(Node&& node) {
hasNewLayout_ = node.hasNewLayout_;
isReferenceBaseline_ = node.isReferenceBaseline_;
isDirty_ = node.isDirty_;
nodeType_ = node.nodeType_;
context_ = node.context_; context_ = node.context_;
flags_ = node.flags_;
measureFunc_ = node.measureFunc_; measureFunc_ = node.measureFunc_;
baselineFunc_ = node.baselineFunc_; baselineFunc_ = node.baselineFunc_;
printFunc_ = node.printFunc_; printFunc_ = node.printFunc_;
@@ -271,10 +273,10 @@ void Node::setConfig(yoga::Config* config) {
} }
void Node::setDirty(bool isDirty) { void Node::setDirty(bool isDirty) {
if (isDirty == flags_.isDirty) { if (isDirty == isDirty_) {
return; return;
} }
flags_.isDirty = isDirty; isDirty_ = isDirty;
if (isDirty && dirtiedFunc_) { if (isDirty && dirtiedFunc_) {
dirtiedFunc_(this); dirtiedFunc_(this);
} }
@@ -473,7 +475,7 @@ void Node::cloneChildrenIfNeeded() {
} }
void Node::markDirtyAndPropagate() { void Node::markDirtyAndPropagate() {
if (!flags_.isDirty) { if (!isDirty_) {
setDirty(true); setDirty(true);
setLayoutComputedFlexBasis(FloatOptional()); setLayoutComputedFlexBasis(FloatOptional());
if (owner_) { if (owner_) {
@@ -483,7 +485,7 @@ void Node::markDirtyAndPropagate() {
} }
void Node::markDirtyAndPropagateDownwards() { void Node::markDirtyAndPropagateDownwards() {
flags_.isDirty = true; isDirty_ = true;
for_each(children_.begin(), children_.end(), [](Node* childNode) { for_each(children_.begin(), children_.end(), [](Node* childNode) {
childNode->markDirtyAndPropagateDownwards(); childNode->markDirtyAndPropagateDownwards();
}); });

View File

@@ -26,20 +26,13 @@ struct YGNode {};
namespace facebook::yoga { namespace facebook::yoga {
#pragma pack(push)
#pragma pack(1)
struct NodeFlags {
bool hasNewLayout : 1;
bool isReferenceBaseline : 1;
bool isDirty : 1;
NodeType nodeType : bitCount<NodeType>();
};
#pragma pack(pop)
class YG_EXPORT Node : public ::YGNode { class YG_EXPORT Node : public ::YGNode {
private: private:
bool hasNewLayout_ : 1 = true;
bool isReferenceBaseline_ : 1 = false;
bool isDirty_ : 1 = false;
NodeType nodeType_ : bitCount<NodeType>() = NodeType::Default;
void* context_ = nullptr; void* context_ = nullptr;
NodeFlags flags_ = {};
YGMeasureFunc measureFunc_ = {nullptr}; YGMeasureFunc measureFunc_ = {nullptr};
YGBaselineFunc baselineFunc_ = {nullptr}; YGBaselineFunc baselineFunc_ = {nullptr};
YGPrintFunc printFunc_ = {nullptr}; YGPrintFunc printFunc_ = {nullptr};
@@ -92,11 +85,11 @@ class YG_EXPORT Node : public ::YGNode {
void print(); void print();
bool getHasNewLayout() const { bool getHasNewLayout() const {
return flags_.hasNewLayout; return hasNewLayout_;
} }
NodeType getNodeType() const { NodeType getNodeType() const {
return flags_.nodeType; return nodeType_;
} }
bool hasMeasureFunc() const noexcept { bool hasMeasureFunc() const noexcept {
@@ -142,7 +135,7 @@ class YG_EXPORT Node : public ::YGNode {
} }
bool isReferenceBaseline() const { bool isReferenceBaseline() const {
return flags_.isReferenceBaseline; return isReferenceBaseline_;
} }
// returns the Node that owns this Node. An owner is used to identify // returns the Node that owns this Node. An owner is used to identify
@@ -175,7 +168,7 @@ class YG_EXPORT Node : public ::YGNode {
} }
bool isDirty() const { bool isDirty() const {
return flags_.isDirty; return isDirty_;
} }
std::array<YGValue, 2> getResolvedDimensions() const { std::array<YGValue, 2> getResolvedDimensions() const {
@@ -250,11 +243,11 @@ class YG_EXPORT Node : public ::YGNode {
} }
void setHasNewLayout(bool hasNewLayout) { void setHasNewLayout(bool hasNewLayout) {
flags_.hasNewLayout = hasNewLayout; hasNewLayout_ = hasNewLayout;
} }
void setNodeType(NodeType nodeType) { void setNodeType(NodeType nodeType) {
flags_.nodeType = nodeType; nodeType_ = nodeType;
} }
void setMeasureFunc(YGMeasureFunc measureFunc); void setMeasureFunc(YGMeasureFunc measureFunc);
@@ -280,7 +273,7 @@ class YG_EXPORT Node : public ::YGNode {
} }
void setIsReferenceBaseline(bool isReferenceBaseline) { void setIsReferenceBaseline(bool isReferenceBaseline) {
flags_.isReferenceBaseline = isReferenceBaseline; isReferenceBaseline_ = isReferenceBaseline;
} }
void setOwner(Node* owner) { void setOwner(Node* owner) {