Skip to content

Commit 40c4552

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Simplify Edge Resolution (#42254)
Summary: Pull Request resolved: #42254 X-link: facebook/yoga#1550 This change aims to simplify how we resolve edges. This operation happens many, many times, and has gotten complex and slow when paired with StyleValuePool. This starts reshaping so that `yoga::Style` can resolve a style prop for a given edge. This is closer to the ideal computed style API to avoid recalcing this so many times, but doesn't address that. This relies on removing the errata related to row-reverse, and cleans up the removal started in the last change. This has no measurable perf effect under CompactValue, but has a >10% uplift in perf when using StyleValueHandle, where we can trivially check if a handle points to a defined value without resolving it, but only within `yoga::Style` since we don't expose the handle outside of it. More quantifiably, we go from 2.35 million StyleValuePool reads to 993k. The rest are checks on the handle. Reviewed By: joevilches Differential Revision: D52605596 fbshipit-source-id: 0b366963a899e376f99ce3d75cd5f14a25d60cec
1 parent 0e4a3da commit 40c4552

File tree

14 files changed

+653
-715
lines changed

14 files changed

+653
-715
lines changed

packages/react-native/ReactCommon/yoga/yoga/YGNodeLayout.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,39 @@ float getResolvedLayoutProperty(const YGNodeConstRef nodeRef, const Edge edge) {
2525

2626
if (edge == Edge::Start) {
2727
if (node->getLayout().direction() == Direction::RTL) {
28-
return (node->getLayout().*LayoutMember)(Edge::Right);
28+
return (node->getLayout().*LayoutMember)(PhysicalEdge::Right);
2929
} else {
30-
return (node->getLayout().*LayoutMember)(Edge::Left);
30+
return (node->getLayout().*LayoutMember)(PhysicalEdge::Left);
3131
}
3232
}
3333

3434
if (edge == Edge::End) {
3535
if (node->getLayout().direction() == Direction::RTL) {
36-
return (node->getLayout().*LayoutMember)(Edge::Left);
36+
return (node->getLayout().*LayoutMember)(PhysicalEdge::Left);
3737
} else {
38-
return (node->getLayout().*LayoutMember)(Edge::Right);
38+
return (node->getLayout().*LayoutMember)(PhysicalEdge::Right);
3939
}
4040
}
4141

42-
return (node->getLayout().*LayoutMember)(edge);
42+
return (node->getLayout().*LayoutMember)(static_cast<PhysicalEdge>(edge));
4343
}
4444

4545
} // namespace
4646

4747
float YGNodeLayoutGetLeft(const YGNodeConstRef node) {
48-
return resolveRef(node)->getLayout().position(Edge::Left);
48+
return resolveRef(node)->getLayout().position(PhysicalEdge::Left);
4949
}
5050

5151
float YGNodeLayoutGetTop(const YGNodeConstRef node) {
52-
return resolveRef(node)->getLayout().position(Edge::Top);
52+
return resolveRef(node)->getLayout().position(PhysicalEdge::Top);
5353
}
5454

5555
float YGNodeLayoutGetRight(const YGNodeConstRef node) {
56-
return resolveRef(node)->getLayout().position(Edge::Right);
56+
return resolveRef(node)->getLayout().position(PhysicalEdge::Right);
5757
}
5858

5959
float YGNodeLayoutGetBottom(const YGNodeConstRef node) {
60-
return resolveRef(node)->getLayout().position(Edge::Bottom);
60+
return resolveRef(node)->getLayout().position(PhysicalEdge::Bottom);
6161
}
6262

6363
float YGNodeLayoutGetWidth(const YGNodeConstRef node) {

packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ static inline void setFlexStartLayoutPosition(
2020
const FlexDirection axis,
2121
const float containingBlockWidth) {
2222
child->setLayoutPosition(
23-
child->getFlexStartMargin(axis, direction, containingBlockWidth) +
23+
child->style().computeFlexStartMargin(
24+
axis, direction, containingBlockWidth) +
2425
parent->getLayout().border(flexStartEdge(axis)) +
2526
parent->getLayout().padding(flexStartEdge(axis)),
2627
flexStartEdge(axis));
@@ -36,7 +37,8 @@ static inline void setFlexEndLayoutPosition(
3637
getPositionOfOppositeEdge(
3738
parent->getLayout().border(flexEndEdge(axis)) +
3839
parent->getLayout().padding(flexEndEdge(axis)) +
39-
child->getFlexEndMargin(axis, direction, containingBlockWidth),
40+
child->style().computeFlexEndMargin(
41+
axis, direction, containingBlockWidth),
4042
axis,
4143
parent,
4244
child),
@@ -57,12 +59,13 @@ static inline void setCenterLayoutPosition(
5759
parent->getLayout().padding(flexEndEdge(axis));
5860
const float childOuterSize =
5961
child->getLayout().measuredDimension(dimension(axis)) +
60-
child->getMarginForAxis(axis, containingBlockWidth);
62+
child->style().computeMarginForAxis(axis, containingBlockWidth);
6163
child->setLayoutPosition(
6264
(parentContentBoxSize - childOuterSize) / 2.0f +
6365
parent->getLayout().border(flexStartEdge(axis)) +
6466
parent->getLayout().padding(flexStartEdge(axis)) +
65-
child->getFlexStartMargin(axis, direction, containingBlockWidth),
67+
child->style().computeFlexStartMargin(
68+
axis, direction, containingBlockWidth),
6669
flexStartEdge(axis));
6770
}
6871

@@ -150,30 +153,32 @@ static void positionAbsoluteChildLegacy(
150153
: ((resolveChildAlignment(parent, child) == Align::FlexEnd) ^
151154
(parent->style().flexWrap() == Wrap::WrapReverse));
152155

153-
if (child->isFlexEndPositionDefined(axis, direction) &&
154-
!child->isFlexStartPositionDefined(axis, direction)) {
156+
if (child->style().isFlexEndPositionDefined(axis, direction) &&
157+
!child->style().isFlexStartPositionDefined(axis, direction)) {
155158
child->setLayoutPosition(
156159
containingNode->getLayout().measuredDimension(dimension(axis)) -
157160
child->getLayout().measuredDimension(dimension(axis)) -
158-
containingNode->getFlexEndBorder(axis, direction) -
159-
child->getFlexEndMargin(
161+
containingNode->style().computeFlexEndBorder(axis, direction) -
162+
child->style().computeFlexEndMargin(
160163
axis,
161164
direction,
162165
isAxisRow ? containingBlockWidth : containingBlockHeight) -
163-
child->getFlexEndPosition(
166+
child->style().computeFlexEndPosition(
164167
axis,
165168
direction,
166169
isAxisRow ? containingBlockWidth : containingBlockHeight),
167170
flexStartEdge(axis));
168171
} else if (
169-
!child->isFlexStartPositionDefined(axis, direction) && shouldCenter) {
172+
!child->style().isFlexStartPositionDefined(axis, direction) &&
173+
shouldCenter) {
170174
child->setLayoutPosition(
171175
(parent->getLayout().measuredDimension(dimension(axis)) -
172176
child->getLayout().measuredDimension(dimension(axis))) /
173177
2.0f,
174178
flexStartEdge(axis));
175179
} else if (
176-
!child->isFlexStartPositionDefined(axis, direction) && shouldFlexEnd) {
180+
!child->style().isFlexStartPositionDefined(axis, direction) &&
181+
shouldFlexEnd) {
177182
child->setLayoutPosition(
178183
(parent->getLayout().measuredDimension(dimension(axis)) -
179184
child->getLayout().measuredDimension(dimension(axis))),
@@ -218,25 +223,29 @@ static void positionAbsoluteChildImpl(
218223
// to the flex-start edge because this algorithm works by positioning on the
219224
// flex-start edge and then filling in the flex-end direction at the end if
220225
// necessary.
221-
if (child->isInlineStartPositionDefined(axis, direction)) {
226+
if (child->style().isInlineStartPositionDefined(axis, direction)) {
222227
const float positionRelativeToInlineStart =
223-
child->getInlineStartPosition(axis, direction, containingBlockSize) +
224-
containingNode->getInlineStartBorder(axis, direction) +
225-
child->getInlineStartMargin(axis, direction, containingBlockSize);
228+
child->style().computeInlineStartPosition(
229+
axis, direction, containingBlockSize) +
230+
containingNode->style().computeInlineStartBorder(axis, direction) +
231+
child->style().computeInlineStartMargin(
232+
axis, direction, containingBlockSize);
226233
const float positionRelativeToFlexStart =
227234
inlineStartEdge(axis, direction) != flexStartEdge(axis)
228235
? getPositionOfOppositeEdge(
229236
positionRelativeToInlineStart, axis, containingNode, child)
230237
: positionRelativeToInlineStart;
231238

232239
child->setLayoutPosition(positionRelativeToFlexStart, flexStartEdge(axis));
233-
} else if (child->isInlineEndPositionDefined(axis, direction)) {
240+
} else if (child->style().isInlineEndPositionDefined(axis, direction)) {
234241
const float positionRelativeToInlineStart =
235242
containingNode->getLayout().measuredDimension(dimension(axis)) -
236243
child->getLayout().measuredDimension(dimension(axis)) -
237-
containingNode->getInlineEndBorder(axis, direction) -
238-
child->getInlineEndMargin(axis, direction, containingBlockSize) -
239-
child->getInlineEndPosition(axis, direction, containingBlockSize);
244+
containingNode->style().computeInlineEndBorder(axis, direction) -
245+
child->style().computeInlineEndMargin(
246+
axis, direction, containingBlockSize) -
247+
child->style().computeInlineEndPosition(
248+
axis, direction, containingBlockSize);
240249
const float positionRelativeToFlexStart =
241250
inlineStartEdge(axis, direction) != flexStartEdge(axis)
242251
? getPositionOfOppositeEdge(
@@ -303,10 +312,10 @@ void layoutAbsoluteChild(
303312
SizingMode childWidthSizingMode = SizingMode::MaxContent;
304313
SizingMode childHeightSizingMode = SizingMode::MaxContent;
305314

306-
auto marginRow =
307-
child->getMarginForAxis(FlexDirection::Row, containingBlockWidth);
308-
auto marginColumn =
309-
child->getMarginForAxis(FlexDirection::Column, containingBlockWidth);
315+
auto marginRow = child->style().computeMarginForAxis(
316+
FlexDirection::Row, containingBlockWidth);
317+
auto marginColumn = child->style().computeMarginForAxis(
318+
FlexDirection::Column, containingBlockWidth);
310319

311320
if (child->hasDefiniteLength(Dimension::Width, containingBlockWidth)) {
312321
childWidth = child->getResolvedDimension(Dimension::Width)
@@ -316,15 +325,19 @@ void layoutAbsoluteChild(
316325
} else {
317326
// If the child doesn't have a specified width, compute the width based on
318327
// the left/right offsets if they're defined.
319-
if (child->isFlexStartPositionDefined(FlexDirection::Row, direction) &&
320-
child->isFlexEndPositionDefined(FlexDirection::Row, direction)) {
328+
if (child->style().isFlexStartPositionDefined(
329+
FlexDirection::Row, direction) &&
330+
child->style().isFlexEndPositionDefined(
331+
FlexDirection::Row, direction)) {
321332
childWidth =
322333
containingNode->getLayout().measuredDimension(Dimension::Width) -
323-
(containingNode->getFlexStartBorder(FlexDirection::Row, direction) +
324-
containingNode->getFlexEndBorder(FlexDirection::Row, direction)) -
325-
(child->getFlexStartPosition(
334+
(containingNode->style().computeFlexStartBorder(
335+
FlexDirection::Row, direction) +
336+
containingNode->style().computeFlexEndBorder(
337+
FlexDirection::Row, direction)) -
338+
(child->style().computeFlexStartPosition(
326339
FlexDirection::Row, direction, containingBlockWidth) +
327-
child->getFlexEndPosition(
340+
child->style().computeFlexEndPosition(
328341
FlexDirection::Row, direction, containingBlockWidth));
329342
childWidth = boundAxis(
330343
child,
@@ -343,16 +356,19 @@ void layoutAbsoluteChild(
343356
} else {
344357
// If the child doesn't have a specified height, compute the height based
345358
// on the top/bottom offsets if they're defined.
346-
if (child->isFlexStartPositionDefined(FlexDirection::Column, direction) &&
347-
child->isFlexEndPositionDefined(FlexDirection::Column, direction)) {
359+
if (child->style().isFlexStartPositionDefined(
360+
FlexDirection::Column, direction) &&
361+
child->style().isFlexEndPositionDefined(
362+
FlexDirection::Column, direction)) {
348363
childHeight =
349364
containingNode->getLayout().measuredDimension(Dimension::Height) -
350-
(containingNode->getFlexStartBorder(
365+
(containingNode->style().computeFlexStartBorder(
351366
FlexDirection::Column, direction) +
352-
containingNode->getFlexEndBorder(FlexDirection::Column, direction)) -
353-
(child->getFlexStartPosition(
367+
containingNode->style().computeFlexEndBorder(
368+
FlexDirection::Column, direction)) -
369+
(child->style().computeFlexStartPosition(
354370
FlexDirection::Column, direction, containingBlockHeight) +
355-
child->getFlexEndPosition(
371+
child->style().computeFlexEndPosition(
356372
FlexDirection::Column, direction, containingBlockHeight));
357373
childHeight = boundAxis(
358374
child,
@@ -414,9 +430,11 @@ void layoutAbsoluteChild(
414430
depth,
415431
generationCount);
416432
childWidth = child->getLayout().measuredDimension(Dimension::Width) +
417-
child->getMarginForAxis(FlexDirection::Row, containingBlockWidth);
433+
child->style().computeMarginForAxis(
434+
FlexDirection::Row, containingBlockWidth);
418435
childHeight = child->getLayout().measuredDimension(Dimension::Height) +
419-
child->getMarginForAxis(FlexDirection::Column, containingBlockWidth);
436+
child->style().computeMarginForAxis(
437+
FlexDirection::Column, containingBlockWidth);
420438
}
421439

422440
calculateLayoutInternal(
@@ -479,11 +497,12 @@ void layoutAbsoluteDescendants(
479497
const float containingBlockWidth = absoluteErrata
480498
? containingNodeAvailableInnerWidth
481499
: containingNode->getLayout().measuredDimension(Dimension::Width) -
482-
containingNode->getBorderForAxis(FlexDirection::Row);
500+
containingNode->style().computeBorderForAxis(FlexDirection::Row);
483501
const float containingBlockHeight = absoluteErrata
484502
? containingNodeAvailableInnerHeight
485503
: containingNode->getLayout().measuredDimension(Dimension::Height) -
486-
containingNode->getBorderForAxis(FlexDirection::Column);
504+
containingNode->style().computeBorderForAxis(
505+
FlexDirection::Column);
487506

488507
layoutAbsoluteChild(
489508
containingNode,

packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ float calculateBaseline(const yoga::Node* node) {
5757
}
5858

5959
const float baseline = calculateBaseline(baselineChild);
60-
return baseline + baselineChild->getLayout().position(Edge::Top);
60+
return baseline + baselineChild->getLayout().position(PhysicalEdge::Top);
6161
}
6262

6363
bool isBaselineLayout(const yoga::Node* node) {

packages/react-native/ReactCommon/yoga/yoga/algorithm/BoundAxis.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ inline float paddingAndBorderForAxis(
2222
const float widthSize) {
2323
// The total padding/border for a given axis does not depend on the direction
2424
// so hardcoding LTR here to avoid piping direction to this function
25-
return node->getInlineStartPaddingAndBorder(axis, Direction::LTR, widthSize) +
26-
node->getInlineEndPaddingAndBorder(axis, Direction::LTR, widthSize);
25+
return node->style().computeInlineStartPaddingAndBorder(
26+
axis, Direction::LTR, widthSize) +
27+
node->style().computeInlineEndPaddingAndBorder(
28+
axis, Direction::LTR, widthSize);
2729
}
2830

2931
inline FloatOptional boundAxisWithinMinAndMax(

0 commit comments

Comments
 (0)