Skip to content

Commit

Permalink
Remove BitUtils Usage in YGNode (microsoft#1250)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/yoga#1250

Pull Request resolved: facebook#36988

BitUtils functions in Yoga are like bit fields, with more steps, and more error prone (you need to work with explicit offsets). Replace usage with a bitfield struct.

Changelog: [Internal]

Differential Revision: https://internalfb.com/D45133645

fbshipit-source-id: 56bd37c7e507f9172437a88772d142edede52f9d
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Apr 20, 2023
1 parent 65f5cd7 commit 92d2eba
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 52 deletions.
36 changes: 15 additions & 21 deletions packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
#include "YGNode.h"
#include <algorithm>
#include <iostream>
#include "CompactValue.h"
#include "Utils.h"

using namespace facebook;
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_;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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_) {
Expand All @@ -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();
});
Expand All @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down
60 changes: 29 additions & 31 deletions packages/react-native/ReactCommon/yoga/yoga/YGNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include <cstdint>
#include <stdio.h>
#include "BitUtils.h"
#include "CompactValue.h"
#include "YGConfig.h"
#include "YGLayout.h"
Expand All @@ -20,24 +19,29 @@

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*);
using BaselineWithContextFn = float (*)(YGNode*, float, float, void*);
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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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();
}
Expand Down Expand Up @@ -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<YGNodeType>(flags, nodeType_);
return static_cast<YGNodeType>(flags_.nodeType);
}

bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; }
Expand All @@ -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
Expand Down Expand Up @@ -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<YGValue, 2> getResolvedDimensions() const {
return resolvedDimensions_;
Expand Down Expand Up @@ -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<YGNodeType>(
flags, nodeType_, nodeType);
flags_.nodeType = static_cast<uint8_t>(nodeType);
}

void setMeasureFunc(YGMeasureFunc measureFunc);
Expand All @@ -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) {
Expand All @@ -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; }
Expand Down

0 comments on commit 92d2eba

Please sign in to comment.