Skip to content

Commit f349060

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 e02baf6 commit f349060

9 files changed

+83
-1
lines changed

packages/react-reconciler/src/ReactFiber.js

Lines changed: 71 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,75 @@ 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, key - defined at the bottom as dynamic properties
255+
elementType: null,
256+
type: null,
257+
stateNode: null,
258+
259+
// Fiber
260+
return: null,
261+
child: null,
262+
sibling: null,
263+
index: 0,
264+
265+
ref: null,
266+
refCleanup: null,
267+
268+
// pendingProps - defined at the bottom as dynamic properties
269+
memoizedProps: null,
270+
updateQueue: null,
271+
memoizedState: null,
272+
dependencies: null,
273+
274+
// Effects
275+
flags: NoFlags,
276+
subtreeFlags: NoFlags,
277+
deletions: null,
278+
279+
lanes: NoLanes,
280+
childLanes: NoLanes,
281+
282+
alternate: null,
283+
284+
// dynamic properties at the end for more efficient hermes bytecode
285+
tag,
286+
key,
287+
pendingProps,
288+
mode,
289+
};
290+
291+
if (enableProfilerTimer) {
292+
fiber.actualDuration = 0;
293+
fiber.actualStartTime = -1;
294+
fiber.selfBaseDuration = 0;
295+
fiber.treeBaseDuration = 0;
296+
}
297+
298+
if (__DEV__) {
299+
fiber._debugInfo = null;
300+
fiber._debugOwner = null;
301+
fiber._debugNeedsRemount = false;
302+
fiber._debugHookTypes = null;
303+
304+
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
305+
Object.preventExtensions(fiber);
306+
}
307+
}
308+
return fiber;
309+
}
310+
311+
const createFiber = enableObjectFiber
312+
? createFiberImplObject
313+
: createFiberImplClass;
314+
245315
function shouldConstruct(Component: Function) {
246316
const prototype = Component.prototype;
247317
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
@@ -22,5 +22,6 @@ export const consoleManagedByDevToolsDuringStrictMode = __VARIANT__;
2222
export const disableDefaultPropsExceptForClasses = __VARIANT__;
2323
export const enableAddPropertiesFastPath = __VARIANT__;
2424
export const enableFastJSX = __VARIANT__;
25+
export const enableObjectFiber = __VARIANT__;
2526
export const enableShallowPropDiffing = __VARIANT__;
2627
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
@@ -24,6 +24,7 @@ export const {
2424
disableDefaultPropsExceptForClasses,
2525
enableAddPropertiesFastPath,
2626
enableFastJSX,
27+
enableObjectFiber,
2728
enableShallowPropDiffing,
2829
passChildrenWhenCloningPersistedNodes,
2930
} = 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
@@ -96,6 +96,7 @@ export const enableRenderableContext = true;
9696
export const enableReactTestRendererWarning = true;
9797
export const disableDefaultPropsExceptForClasses = true;
9898

99+
export const enableObjectFiber = false;
99100
export const enableOwnerStacks = false;
100101

101102
// 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
@@ -90,6 +90,7 @@ export const enableAddPropertiesFastPath = false;
9090

9191
export const renameElementSymbol = false;
9292

93+
export const enableObjectFiber = false;
9394
export const enableOwnerStacks = false;
9495
export const enableShallowPropDiffing = false;
9596

packages/shared/forks/ReactFeatureFlags.www.js

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

123+
export const enableObjectFiber = false;
123124
export const enableOwnerStacks = false;
124125
export const enableShallowPropDiffing = false;
125126

0 commit comments

Comments
 (0)