Skip to content

Commit d3d2451

Browse files
authored
Use a single lane per priority level (#20791)
(Except transitions and retries.) The idea is that the only priorities that benefit from multiple parallel updates are the ones that might suspend: transitions and retries. All other priorities, including the ones that are interruptible like Continuous and Idle, don't need multiple lanes because it's better to batch everything together.
1 parent b593a6f commit d3d2451

File tree

2 files changed

+200
-190
lines changed

2 files changed

+200
-190
lines changed

Diff for: packages/react-reconciler/src/ReactFiberLane.new.js

+100-95
Original file line numberDiff line numberDiff line change
@@ -85,38 +85,49 @@ export const SyncLane: Lane = /* */ 0b0000000000000000000
8585
export const SyncBatchedLane: Lane = /* */ 0b0000000000000000000000000000010;
8686

8787
export const InputDiscreteHydrationLane: Lane = /* */ 0b0000000000000000000000000000100;
88-
const InputDiscreteLanes: Lanes = /* */ 0b0000000000000000000000000011000;
88+
const InputDiscreteLane: Lanes = /* */ 0b0000000000000000000000000001000;
8989

9090
const InputContinuousHydrationLane: Lane = /* */ 0b0000000000000000000000000100000;
91-
const InputContinuousLanes: Lanes = /* */ 0b0000000000000000000000011000000;
91+
const InputContinuousLane: Lanes = /* */ 0b0000000000000000000000001000000;
9292

9393
export const DefaultHydrationLane: Lane = /* */ 0b0000000000000000000000100000000;
94-
export const DefaultLanes: Lanes = /* */ 0b0000000000000000000111000000000;
94+
export const DefaultLane: Lanes = /* */ 0b0000000000000000000001000000000;
9595

9696
const TransitionHydrationLane: Lane = /* */ 0b0000000000000000001000000000000;
9797
const TransitionLanes: Lanes = /* */ 0b0000000001111111110000000000000;
98-
const FirstTransitionLane: Lane = /* */ 0b0000000000000000010000000000000;
98+
const TransitionLane1: Lane = /* */ 0b0000000000000000010000000000000;
99+
const TransitionLane2: Lane = /* */ 0b0000000000000000100000000000000;
100+
const TransitionLane3: Lane = /* */ 0b0000000000000001000000000000000;
101+
const TransitionLane4: Lane = /* */ 0b0000000000000010000000000000000;
102+
const TransitionLane5: Lane = /* */ 0b0000000000000100000000000000000;
103+
const TransitionLane6: Lane = /* */ 0b0000000000001000000000000000000;
104+
const TransitionLane7: Lane = /* */ 0b0000000000010000000000000000000;
105+
const TransitionLane8: Lane = /* */ 0b0000000000100000000000000000000;
106+
const TransitionLane9: Lane = /* */ 0b0000000001000000000000000000000;
99107

100108
const RetryLanes: Lanes = /* */ 0b0000011110000000000000000000000;
109+
const RetryLane1: Lane = /* */ 0b0000000010000000000000000000000;
110+
const RetryLane2: Lane = /* */ 0b0000000100000000000000000000000;
111+
const RetryLane3: Lane = /* */ 0b0000001000000000000000000000000;
112+
const RetryLane4: Lane = /* */ 0b0000010000000000000000000000000;
101113

102-
const FirstRetryLane: Lanes = /* */ 0b0000000010000000000000000000000;
103-
export const SomeRetryLane: Lane = FirstRetryLane;
114+
export const SomeRetryLane: Lane = RetryLane1;
104115

105116
export const SelectiveHydrationLane: Lane = /* */ 0b0000100000000000000000000000000;
106117

107118
const NonIdleLanes = /* */ 0b0000111111111111111111111111111;
108119

109120
export const IdleHydrationLane: Lane = /* */ 0b0001000000000000000000000000000;
110-
const IdleLanes: Lanes = /* */ 0b0110000000000000000000000000000;
121+
const IdleLane: Lanes = /* */ 0b0010000000000000000000000000000;
111122

112123
export const OffscreenLane: Lane = /* */ 0b1000000000000000000000000000000;
113124

114125
export const NoTimestamp = -1;
115126

116127
let currentUpdateLanePriority: LanePriority = NoLanePriority;
117128

118-
let nextTransitionLane: Lane = FirstTransitionLane;
119-
let nextRetryLane: Lane = FirstRetryLane;
129+
let nextTransitionLane: Lane = TransitionLane1;
130+
let nextRetryLane: Lane = RetryLane1;
120131

121132
export function getCurrentUpdateLanePriority(): LanePriority {
122133
return currentUpdateLanePriority;
@@ -131,78 +142,73 @@ export function setCurrentUpdateLanePriority(newLanePriority: LanePriority) {
131142
let return_highestLanePriority: LanePriority = DefaultLanePriority;
132143

133144
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
134-
if ((SyncLane & lanes) !== NoLanes) {
135-
return_highestLanePriority = SyncLanePriority;
136-
return SyncLane;
137-
}
138-
if ((SyncBatchedLane & lanes) !== NoLanes) {
139-
return_highestLanePriority = SyncBatchedLanePriority;
140-
return SyncBatchedLane;
141-
}
142-
if ((InputDiscreteHydrationLane & lanes) !== NoLanes) {
143-
return_highestLanePriority = InputDiscreteHydrationLanePriority;
144-
return InputDiscreteHydrationLane;
145-
}
146-
const inputDiscreteLanes = InputDiscreteLanes & lanes;
147-
if (inputDiscreteLanes !== NoLanes) {
148-
return_highestLanePriority = InputDiscreteLanePriority;
149-
return inputDiscreteLanes;
150-
}
151-
if ((lanes & InputContinuousHydrationLane) !== NoLanes) {
152-
return_highestLanePriority = InputContinuousHydrationLanePriority;
153-
return InputContinuousHydrationLane;
154-
}
155-
const inputContinuousLanes = InputContinuousLanes & lanes;
156-
if (inputContinuousLanes !== NoLanes) {
157-
return_highestLanePriority = InputContinuousLanePriority;
158-
return inputContinuousLanes;
159-
}
160-
if ((lanes & DefaultHydrationLane) !== NoLanes) {
161-
return_highestLanePriority = DefaultHydrationLanePriority;
162-
return DefaultHydrationLane;
163-
}
164-
const defaultLanes = DefaultLanes & lanes;
165-
if (defaultLanes !== NoLanes) {
166-
return_highestLanePriority = DefaultLanePriority;
167-
return defaultLanes;
168-
}
169-
if ((lanes & TransitionHydrationLane) !== NoLanes) {
170-
return_highestLanePriority = TransitionHydrationPriority;
171-
return TransitionHydrationLane;
172-
}
173-
const transitionLanes = TransitionLanes & lanes;
174-
if (transitionLanes !== NoLanes) {
175-
return_highestLanePriority = TransitionPriority;
176-
return transitionLanes;
177-
}
178-
const retryLanes = RetryLanes & lanes;
179-
if (retryLanes !== NoLanes) {
180-
return_highestLanePriority = RetryLanePriority;
181-
return retryLanes;
182-
}
183-
if (lanes & SelectiveHydrationLane) {
184-
return_highestLanePriority = SelectiveHydrationLanePriority;
185-
return SelectiveHydrationLane;
186-
}
187-
if ((lanes & IdleHydrationLane) !== NoLanes) {
188-
return_highestLanePriority = IdleHydrationLanePriority;
189-
return IdleHydrationLane;
190-
}
191-
const idleLanes = IdleLanes & lanes;
192-
if (idleLanes !== NoLanes) {
193-
return_highestLanePriority = IdleLanePriority;
194-
return idleLanes;
195-
}
196-
if ((OffscreenLane & lanes) !== NoLanes) {
197-
return_highestLanePriority = OffscreenLanePriority;
198-
return OffscreenLane;
199-
}
200-
if (__DEV__) {
201-
console.error('Should have found matching lanes. This is a bug in React.');
145+
switch (getHighestPriorityLane(lanes)) {
146+
case SyncLane:
147+
return_highestLanePriority = SyncLanePriority;
148+
return SyncLane;
149+
case SyncBatchedLane:
150+
return_highestLanePriority = SyncBatchedLanePriority;
151+
return SyncBatchedLane;
152+
case InputDiscreteHydrationLane:
153+
return_highestLanePriority = InputDiscreteHydrationLanePriority;
154+
return InputDiscreteHydrationLane;
155+
case InputDiscreteLane:
156+
return_highestLanePriority = InputDiscreteLanePriority;
157+
return InputDiscreteLane;
158+
case InputContinuousHydrationLane:
159+
return_highestLanePriority = InputContinuousHydrationLanePriority;
160+
return InputContinuousHydrationLane;
161+
case InputContinuousLane:
162+
return_highestLanePriority = InputContinuousLanePriority;
163+
return InputContinuousLane;
164+
case DefaultHydrationLane:
165+
return_highestLanePriority = DefaultHydrationLanePriority;
166+
return DefaultHydrationLane;
167+
case DefaultLane:
168+
return_highestLanePriority = DefaultLanePriority;
169+
return DefaultLane;
170+
case TransitionHydrationLane:
171+
return_highestLanePriority = TransitionHydrationPriority;
172+
return TransitionHydrationLane;
173+
case TransitionLane1:
174+
case TransitionLane2:
175+
case TransitionLane3:
176+
case TransitionLane4:
177+
case TransitionLane5:
178+
case TransitionLane6:
179+
case TransitionLane7:
180+
case TransitionLane8:
181+
case TransitionLane9:
182+
return_highestLanePriority = TransitionPriority;
183+
return lanes & TransitionLanes;
184+
case RetryLane1:
185+
case RetryLane2:
186+
case RetryLane3:
187+
case RetryLane4:
188+
return_highestLanePriority = RetryLanePriority;
189+
return lanes & RetryLanes;
190+
case SelectiveHydrationLane:
191+
return_highestLanePriority = SelectiveHydrationLanePriority;
192+
return SelectiveHydrationLane;
193+
case IdleHydrationLane:
194+
return_highestLanePriority = IdleHydrationLanePriority;
195+
return IdleHydrationLane;
196+
case IdleLane:
197+
return_highestLanePriority = IdleLanePriority;
198+
return IdleLane;
199+
case OffscreenLane:
200+
return_highestLanePriority = OffscreenLanePriority;
201+
return OffscreenLane;
202+
default:
203+
if (__DEV__) {
204+
console.error(
205+
'Should have found matching lanes. This is a bug in React.',
206+
);
207+
}
208+
// This shouldn't be reachable, but as a fallback, return the entire bitmask.
209+
return_highestLanePriority = DefaultLanePriority;
210+
return lanes;
202211
}
203-
// This shouldn't be reachable, but as a fallback, return the entire bitmask.
204-
return_highestLanePriority = DefaultLanePriority;
205-
return lanes;
206212
}
207213

208214
export function schedulerPriorityToLanePriority(
@@ -516,20 +522,17 @@ export function findUpdateLane(lanePriority: LanePriority): Lane {
516522
return SyncLane;
517523
case SyncBatchedLanePriority:
518524
return SyncBatchedLane;
519-
case InputDiscreteLanePriority: {
520-
return pickArbitraryLane(InputDiscreteLanes);
521-
}
522-
case InputContinuousLanePriority: {
523-
return pickArbitraryLane(InputContinuousLanes);
524-
}
525-
case DefaultLanePriority: {
526-
return pickArbitraryLane(DefaultLanes);
527-
}
525+
case InputDiscreteLanePriority:
526+
return InputDiscreteLane;
527+
case InputContinuousLanePriority:
528+
return InputContinuousLane;
529+
case DefaultLanePriority:
530+
return DefaultLane;
528531
case TransitionPriority: // Should be handled by findTransitionLane instead
529532
case RetryLanePriority: // Should be handled by findRetryLane instead
530533
break;
531534
case IdleLanePriority:
532-
return pickArbitraryLane(IdleLanes);
535+
return IdleLane;
533536
default:
534537
// The remaining priorities are not valid for updates
535538
break;
@@ -549,7 +552,7 @@ export function claimNextTransitionLane(): Lane {
549552
const lane = nextTransitionLane;
550553
nextTransitionLane <<= 1;
551554
if ((nextTransitionLane & TransitionLanes) === 0) {
552-
nextTransitionLane = FirstTransitionLane;
555+
nextTransitionLane = TransitionLane1;
553556
}
554557
return lane;
555558
}
@@ -558,7 +561,7 @@ export function claimNextRetryLane(): Lane {
558561
const lane = nextRetryLane;
559562
nextRetryLane <<= 1;
560563
if ((nextRetryLane & RetryLanes) === 0) {
561-
nextRetryLane = FirstRetryLane;
564+
nextRetryLane = RetryLane1;
562565
}
563566
return lane;
564567
}
@@ -650,7 +653,7 @@ export function markRootUpdated(
650653
// We don't do this if the incoming update is idle, because we never process
651654
// idle updates until after all the regular updates have finished; there's no
652655
// way it could unblock a transition.
653-
if ((updateLane & IdleLanes) === NoLanes) {
656+
if (updateLane !== IdleLane) {
654657
root.suspendedLanes = NoLanes;
655658
root.pingedLanes = NoLanes;
656659
}
@@ -692,11 +695,13 @@ export function markRootExpired(root: FiberRoot, expiredLanes: Lanes) {
692695
}
693696

694697
export function markDiscreteUpdatesExpired(root: FiberRoot) {
695-
root.expiredLanes |= InputDiscreteLanes & root.pendingLanes;
698+
if (root.pendingLanes & InputDiscreteLane) {
699+
root.expiredLanes |= InputDiscreteLane;
700+
}
696701
}
697702

698703
export function hasDiscreteLanes(lanes: Lanes) {
699-
return (lanes & InputDiscreteLanes) !== NoLanes;
704+
return (lanes & InputDiscreteLane) !== NoLanes;
700705
}
701706

702707
export function markRootMutableRead(root: FiberRoot, updateLane: Lane) {

0 commit comments

Comments
 (0)