Skip to content

Commit 2c73dbd

Browse files
davidaureliofacebook-github-bot
authored andcommitted
Use Bitfield in YGNode and YGStyle
Summary: @public Replaces the usage of C++ bitfields with our portable `Bitfield` class. Reviewed By: SidharthGuglani Differential Revision: D16649875 fbshipit-source-id: 539f016d5e1c9a8c48cc9bacbbf6ed985e385e69
1 parent f33a623 commit 2c73dbd

File tree

4 files changed

+125
-159
lines changed

4 files changed

+125
-159
lines changed

ReactCommon/yoga/yoga/Bitfield.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ class Bitfield {
9595
template <size_t Idx>
9696
using TypeAt = typename detail::IndexedType<Idx, Fields...>::Type;
9797

98+
template <size_t Idx, typename Value, typename... Values>
99+
static constexpr Storage initStorage(Value value, Values... values) {
100+
return ((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx)) |
101+
initStorage<Idx + 1, Values...>(values...);
102+
}
103+
104+
template <size_t Idx>
105+
static constexpr Storage initStorage() {
106+
return Storage{0};
107+
}
108+
109+
Storage storage_ = 0;
110+
111+
public:
98112
template <size_t Idx>
99113
class Ref {
100114
Bitfield& bitfield_;
@@ -111,20 +125,6 @@ class Bitfield {
111125
}
112126
};
113127

114-
template <size_t Idx, typename Value, typename... Values>
115-
static constexpr Storage initStorage(Value value, Values... values) {
116-
return ((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx)) |
117-
initStorage<Idx + 1, Values...>(values...);
118-
}
119-
120-
template <size_t Idx>
121-
static constexpr Storage initStorage() {
122-
return Storage{0};
123-
}
124-
125-
Storage storage_ = 0;
126-
127-
public:
128128
constexpr Bitfield() = default;
129129
constexpr Bitfield(Fields... values) : storage_{initStorage<0>(values...)} {}
130130

ReactCommon/yoga/yoga/YGNode.cpp

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,7 @@ using facebook::yoga::detail::CompactValue;
1515

1616
YGNode::YGNode(YGNode&& node) {
1717
context_ = node.context_;
18-
hasNewLayout_ = node.hasNewLayout_;
19-
isReferenceBaseline_ = node.isReferenceBaseline_;
20-
isDirty_ = node.isDirty_;
21-
nodeType_ = node.nodeType_;
22-
measureUsesContext_ = node.measureUsesContext_;
23-
baselineUsesContext_ = node.baselineUsesContext_;
24-
printUsesContext_ = node.printUsesContext_;
25-
useWebDefaults_ = node.useWebDefaults_;
18+
flags_ = node.flags_;
2619
measure_ = node.measure_;
2720
baseline_ = node.baseline_;
2821
print_ = node.print_;
@@ -48,7 +41,7 @@ YGNode::YGNode(const YGNode& node, YGConfigRef config) : YGNode{node} {
4841

4942
void YGNode::print(void* printContext) {
5043
if (print_.noContext != nullptr) {
51-
if (printUsesContext_) {
44+
if (flags_.at<printUsesContext_>()) {
5245
print_.withContext(this, printContext);
5346
} else {
5447
print_.noContext(this);
@@ -154,14 +147,14 @@ YGSize YGNode::measure(
154147
YGMeasureMode heightMode,
155148
void* layoutContext) {
156149

157-
return measureUsesContext_
150+
return flags_.at<measureUsesContext_>()
158151
? measure_.withContext(
159152
this, width, widthMode, height, heightMode, layoutContext)
160153
: measure_.noContext(this, width, widthMode, height, heightMode);
161154
}
162155

163156
float YGNode::baseline(float width, float height, void* layoutContext) {
164-
return baselineUsesContext_
157+
return flags_.at<baselineUsesContext_>()
165158
? baseline_.withContext(this, width, height, layoutContext)
166159
: baseline_.noContext(this, width, height);
167160
}
@@ -172,7 +165,7 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) {
172165
if (measureFunc.noContext == nullptr) {
173166
// TODO: t18095186 Move nodeType to opt-in function and mark appropriate
174167
// places in Litho
175-
nodeType_ = YGNodeTypeDefault;
168+
flags_.at<nodeType_>() = YGNodeTypeDefault;
176169
} else {
177170
YGAssertWithNode(
178171
this,
@@ -188,14 +181,14 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) {
188181
}
189182

190183
void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) {
191-
measureUsesContext_ = false;
184+
flags_.at<measureUsesContext_>() = false;
192185
decltype(YGNode::measure_) m;
193186
m.noContext = measureFunc;
194187
setMeasureFunc(m);
195188
}
196189

197190
void YGNode::setMeasureFunc(MeasureWithContextFn measureFunc) {
198-
measureUsesContext_ = true;
191+
flags_.at<measureUsesContext_>() = true;
199192
decltype(YGNode::measure_) m;
200193
m.withContext = measureFunc;
201194
setMeasureFunc(m);
@@ -214,10 +207,10 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) {
214207
}
215208

216209
void YGNode::setDirty(bool isDirty) {
217-
if (isDirty == isDirty_) {
210+
if (isDirty == flags_.at<isDirty_>()) {
218211
return;
219212
}
220-
isDirty_ = isDirty;
213+
flags_.at<isDirty_>() = isDirty;
221214
if (isDirty && dirtied_) {
222215
dirtied_(this);
223216
}
@@ -357,7 +350,7 @@ YGValue YGNode::resolveFlexBasisPtr() const {
357350
return flexBasis;
358351
}
359352
if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) {
360-
return useWebDefaults_ ? YGValueAuto : YGValueZero;
353+
return flags_.at<useWebDefaults_>() ? YGValueAuto : YGValueZero;
361354
}
362355
return YGValueAuto;
363356
}
@@ -396,7 +389,7 @@ void YGNode::cloneChildrenIfNeeded(void* cloneContext) {
396389
}
397390

398391
void YGNode::markDirtyAndPropogate() {
399-
if (!isDirty_) {
392+
if (!flags_.at<isDirty_>()) {
400393
setDirty(true);
401394
setLayoutComputedFlexBasis(YGFloatOptional());
402395
if (owner_) {
@@ -406,7 +399,7 @@ void YGNode::markDirtyAndPropogate() {
406399
}
407400

408401
void YGNode::markDirtyAndPropogateDownwards() {
409-
isDirty_ = true;
402+
flags_.at<isDirty_>() = true;
410403
for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) {
411404
childNode->markDirtyAndPropogateDownwards();
412405
});
@@ -433,11 +426,12 @@ float YGNode::resolveFlexShrink() const {
433426
if (!style_.flexShrink().isUndefined()) {
434427
return style_.flexShrink().unwrap();
435428
}
436-
if (!useWebDefaults_ && !style_.flex().isUndefined() &&
429+
if (!flags_.at<useWebDefaults_>() && !style_.flex().isUndefined() &&
437430
style_.flex().unwrap() < 0.0f) {
438431
return -style_.flex().unwrap();
439432
}
440-
return useWebDefaults_ ? kWebDefaultFlexShrink : kDefaultFlexShrink;
433+
return flags_.at<useWebDefaults_>() ? kWebDefaultFlexShrink
434+
: kDefaultFlexShrink;
441435
}
442436

443437
bool YGNode::isNodeFlexible() {
@@ -582,7 +576,7 @@ void YGNode::reset() {
582576

583577
clearChildren();
584578

585-
auto webDefaults = useWebDefaults_;
579+
auto webDefaults = flags_.at<useWebDefaults_>();
586580
*this = YGNode{getConfig()};
587581
if (webDefaults) {
588582
useWebDefaults();

ReactCommon/yoga/yoga/YGNode.h

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#pragma once
88
#include <cstdint>
99
#include <stdio.h>
10+
#include "Bitfield.h"
1011
#include "CompactValue.h"
1112
#include "YGConfig.h"
1213
#include "YGLayout.h"
@@ -23,15 +24,20 @@ struct YGNode {
2324
using PrintWithContextFn = void (*)(YGNode*, void*);
2425

2526
private:
27+
static constexpr size_t hasNewLayout_ = 0;
28+
static constexpr size_t isReferenceBaseline_ = 1;
29+
static constexpr size_t isDirty_ = 2;
30+
static constexpr size_t nodeType_ = 3;
31+
static constexpr size_t measureUsesContext_ = 4;
32+
static constexpr size_t baselineUsesContext_ = 5;
33+
static constexpr size_t printUsesContext_ = 6;
34+
static constexpr size_t useWebDefaults_ = 7;
35+
2636
void* context_ = nullptr;
27-
bool hasNewLayout_ : 1;
28-
bool isReferenceBaseline_ : 1;
29-
bool isDirty_ : 1;
30-
YGNodeType nodeType_ : 1;
31-
bool measureUsesContext_ : 1;
32-
bool baselineUsesContext_ : 1;
33-
bool printUsesContext_ : 1;
34-
bool useWebDefaults_ : 1;
37+
using Flags = facebook::yoga::
38+
Bitfield<uint8_t, bool, bool, bool, YGNodeType, bool, bool, bool, bool>;
39+
Flags flags_ =
40+
{true, false, false, YGNodeTypeDefault, false, false, false, false};
3541
uint8_t reserved_ = 0;
3642
union {
3743
YGMeasureFunc noContext;
@@ -63,7 +69,7 @@ struct YGNode {
6369
void setBaselineFunc(decltype(baseline_));
6470

6571
void useWebDefaults() {
66-
useWebDefaults_ = true;
72+
flags_.at<useWebDefaults_>() = true;
6773
style_.flexDirection() = YGFlexDirectionRow;
6874
style_.alignContent() = YGAlignStretch;
6975
}
@@ -79,17 +85,8 @@ struct YGNode {
7985

8086
public:
8187
YGNode() : YGNode{YGConfigGetDefault()} {}
82-
explicit YGNode(const YGConfigRef config)
83-
: hasNewLayout_{true},
84-
isReferenceBaseline_{false},
85-
isDirty_{false},
86-
nodeType_{YGNodeTypeDefault},
87-
measureUsesContext_{false},
88-
baselineUsesContext_{false},
89-
printUsesContext_{false},
90-
useWebDefaults_{config->useWebDefaults},
91-
config_{config} {
92-
if (useWebDefaults_) {
88+
explicit YGNode(const YGConfigRef config) : config_{config} {
89+
if (config->useWebDefaults) {
9390
useWebDefaults();
9491
}
9592
};
@@ -116,9 +113,9 @@ struct YGNode {
116113

117114
void print(void*);
118115

119-
bool getHasNewLayout() const { return hasNewLayout_; }
116+
bool getHasNewLayout() const { return flags_.at<hasNewLayout_>(); }
120117

121-
YGNodeType getNodeType() const { return nodeType_; }
118+
YGNodeType getNodeType() const { return flags_.at<nodeType_>(); }
122119

123120
bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; }
124121

@@ -144,7 +141,7 @@ struct YGNode {
144141

145142
uint32_t getLineIndex() const { return lineIndex_; }
146143

147-
bool isReferenceBaseline() { return isReferenceBaseline_; }
144+
bool isReferenceBaseline() { return flags_.at<isReferenceBaseline_>(); }
148145

149146
// returns the YGNodeRef that owns this YGNode. An owner is used to identify
150147
// the YogaTree that a YGNode belongs to. This method will return the parent
@@ -177,7 +174,7 @@ struct YGNode {
177174

178175
YGConfigRef getConfig() const { return config_; }
179176

180-
bool isDirty() const { return isDirty_; }
177+
bool isDirty() const { return flags_.at<isDirty_>(); }
181178

182179
std::array<YGValue, 2> getResolvedDimensions() const {
183180
return resolvedDimensions_;
@@ -225,17 +222,19 @@ struct YGNode {
225222

226223
void setPrintFunc(YGPrintFunc printFunc) {
227224
print_.noContext = printFunc;
228-
printUsesContext_ = false;
225+
flags_.at<printUsesContext_>() = false;
229226
}
230227
void setPrintFunc(PrintWithContextFn printFunc) {
231228
print_.withContext = printFunc;
232-
printUsesContext_ = true;
229+
flags_.at<printUsesContext_>() = true;
233230
}
234231
void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); }
235232

236-
void setHasNewLayout(bool hasNewLayout) { hasNewLayout_ = hasNewLayout; }
233+
void setHasNewLayout(bool hasNewLayout) {
234+
flags_.at<hasNewLayout_>() = hasNewLayout;
235+
}
237236

238-
void setNodeType(YGNodeType nodeType) { nodeType_ = nodeType; }
237+
void setNodeType(YGNodeType nodeType) { flags_.at<nodeType_>() = nodeType; }
239238

240239
void setMeasureFunc(YGMeasureFunc measureFunc);
241240
void setMeasureFunc(MeasureWithContextFn);
@@ -244,11 +243,11 @@ struct YGNode {
244243
}
245244

246245
void setBaselineFunc(YGBaselineFunc baseLineFunc) {
247-
baselineUsesContext_ = false;
246+
flags_.at<baselineUsesContext_>() = false;
248247
baseline_.noContext = baseLineFunc;
249248
}
250249
void setBaselineFunc(BaselineWithContextFn baseLineFunc) {
251-
baselineUsesContext_ = true;
250+
flags_.at<baselineUsesContext_>() = true;
252251
baseline_.withContext = baseLineFunc;
253252
}
254253
void setBaselineFunc(std::nullptr_t) {
@@ -264,7 +263,7 @@ struct YGNode {
264263
void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; }
265264

266265
void setIsReferenceBaseline(bool isReferenceBaseline) {
267-
isReferenceBaseline_ = isReferenceBaseline;
266+
flags_.at<isReferenceBaseline_>() = isReferenceBaseline;
268267
}
269268

270269
void setOwner(YGNodeRef owner) { owner_ = owner; }

0 commit comments

Comments
 (0)