Skip to content

Commit b7db858

Browse files
committed
Experiment with using an object literal for Fiber creation
Object literals should be faster at least on React Native with Hermes as the JS engine. It might also be interesting to confirm the old comments in this file from years ago are even still valid. Creating an object from a literal should be a simpler operation. It's a bit unfortunate that this introduces a bunch of copied code, but since we rearely update the fields on fibers, this seems like an okay tradeoff for a hot code path. An alternative would be some sort of macro system, but that doesn't seem worth the extra complexity.
1 parent 49a4887 commit b7db858

9 files changed

+80
-1
lines changed

packages/react-reconciler/src/ReactFiber.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
enableDO_NOT_USE_disableStrictPassiveEffect,
3939
enableRenderableContext,
4040
disableLegacyMode,
41+
enableObjectFiber,
4142
enableOwnerStacks,
4243
} from 'shared/ReactFeatureFlags';
4344
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
@@ -232,7 +233,7 @@ function FiberNode(
232233
// is faster.
233234
// 5) It should be easy to port this to a C struct and keep a C implementation
234235
// compatible.
235-
function createFiber(
236+
function createFiberImplClass(
236237
tag: WorkTag,
237238
pendingProps: mixed,
238239
key: null | string,
@@ -242,6 +243,72 @@ function createFiber(
242243
return new FiberNode(tag, pendingProps, key, mode);
243244
}
244245

246+
function createFiberImplObject(
247+
tag: WorkTag,
248+
pendingProps: mixed,
249+
key: null | string,
250+
mode: TypeOfMode,
251+
): Fiber {
252+
const fiber: Fiber = {
253+
// Instance
254+
tag,
255+
key,
256+
elementType: null,
257+
type: null,
258+
stateNode: null,
259+
260+
// Fiber
261+
return: null,
262+
child: null,
263+
sibling: null,
264+
index: 0,
265+
266+
ref: null,
267+
refCleanup: null,
268+
269+
pendingProps,
270+
memoizedProps: null,
271+
updateQueue: null,
272+
memoizedState: null,
273+
dependencies: null,
274+
275+
mode,
276+
277+
// Effects
278+
flags: NoFlags,
279+
subtreeFlags: NoFlags,
280+
deletions: null,
281+
282+
lanes: NoLanes,
283+
childLanes: NoLanes,
284+
285+
alternate: null,
286+
};
287+
288+
if (enableProfilerTimer) {
289+
fiber.actualDuration = 0;
290+
fiber.actualStartTime = -1;
291+
fiber.selfBaseDuration = 0;
292+
fiber.treeBaseDuration = 0;
293+
}
294+
295+
if (__DEV__) {
296+
fiber._debugInfo = null;
297+
fiber._debugOwner = null;
298+
fiber._debugNeedsRemount = false;
299+
fiber._debugHookTypes = null;
300+
301+
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
302+
Object.preventExtensions(fiber);
303+
}
304+
}
305+
return fiber;
306+
}
307+
308+
const createFiber = enableObjectFiber
309+
? createFiberImplObject
310+
: createFiberImplClass;
311+
245312
function shouldConstruct(Component: Function) {
246313
const prototype = Component.prototype;
247314
return !!(prototype && prototype.isReactComponent);

packages/shared/ReactFeatureFlags.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ export const enableTaint = __EXPERIMENTAL__;
8787

8888
export const enablePostpone = __EXPERIMENTAL__;
8989

90+
/**
91+
* Switches Fiber creation to a simple object instead of a constructor.
92+
*/
93+
export const enableObjectFiber = false;
94+
9095
export const enableTransitionTracing = false;
9196

9297
// No known bugs, but needs performance testing

packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ export const enableAddPropertiesFastPath = __VARIANT__;
2424
export const enableDeferRootSchedulingToMicrotask = __VARIANT__;
2525
export const enableFastJSX = __VARIANT__;
2626
export const enableInfiniteRenderLoopDetection = __VARIANT__;
27+
export const enableObjectFiber = __VARIANT__;
2728
export const enableShallowPropDiffing = __VARIANT__;
2829
export const passChildrenWhenCloningPersistedNodes = __VARIANT__;

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const {
2626
enableDeferRootSchedulingToMicrotask,
2727
enableFastJSX,
2828
enableInfiniteRenderLoopDetection,
29+
enableObjectFiber,
2930
enableShallowPropDiffing,
3031
passChildrenWhenCloningPersistedNodes,
3132
} = dynamicFlags;

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const enableLegacyCache = false;
5555
export const enableLegacyFBSupport = false;
5656
export const enableLegacyHidden = false;
5757
export const enableNoCloningMemoCache = false;
58+
export const enableObjectFiber = false;
5859
export const enableOwnerStacks = __EXPERIMENTAL__;
5960
export const enablePostpone = false;
6061
export const enableReactTestRendererWarning = false;

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export const enableRenderableContext = true;
9797
export const enableReactTestRendererWarning = true;
9898
export const disableDefaultPropsExceptForClasses = true;
9999

100+
export const enableObjectFiber = false;
100101
export const enableOwnerStacks = false;
101102

102103
// Flow magic to verify the exports of this file match the original version.

packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const enableLegacyCache = false;
4747
export const enableLegacyFBSupport = false;
4848
export const enableLegacyHidden = false;
4949
export const enableNoCloningMemoCache = false;
50+
export const enableObjectFiber = false;
5051
export const enableOwnerStacks = false;
5152
export const enablePostpone = false;
5253
export const enableProfilerCommitHooks = __PROFILE__;

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const enableAddPropertiesFastPath = false;
9191

9292
export const renameElementSymbol = false;
9393

94+
export const enableObjectFiber = false;
9495
export const enableOwnerStacks = false;
9596
export const enableShallowPropDiffing = false;
9697

packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export const disableStringRefs = false;
122122
export const disableLegacyMode: boolean =
123123
__EXPERIMENTAL__ || dynamicFeatureFlags.disableLegacyMode;
124124

125+
export const enableObjectFiber = false;
125126
export const enableOwnerStacks = false;
126127
export const enableShallowPropDiffing = false;
127128

0 commit comments

Comments
 (0)