New Props parsing infrastructure for perf improvements: visitor pattern vs random-map-access pattern (BaseTextProps and derived props)

Summary:
See commentary at top of stack.

Changelog: [Added][Fabric] New API for efficient props construction

Reviewed By: javache

Differential Revision: D37051020

fbshipit-source-id: 643e433c0d0590cfcd17bc7a43d105bed6ff12ef
This commit is contained in:
Joshua Gross
2022-06-15 23:37:34 -07:00
committed by Facebook GitHub Bot
parent 2ab585ac26
commit af1eae9ea3
10 changed files with 178 additions and 5 deletions
@@ -12,9 +12,27 @@
#include <react/renderer/debug/DebugStringConvertibleItem.h>
#include <react/renderer/graphics/conversions.h>
#define GET_FIELD_VALUE(field, fieldName, defaultValue, rawValue) \
(rawValue.hasValue() ? ({ \
decltype(defaultValue) res; \
fromRawValue(context, rawValue, res); \
res; \
}) \
: defaultValue)
#define REBUILD_FIELD_SWITCH_CASE( \
defaults, rawValue, property, field, fieldName) \
case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \
property.field = \
GET_FIELD_VALUE(field, fieldName, defaults.field, rawValue); \
return; \
}
namespace facebook {
namespace react {
bool BaseTextProps::enablePropIteratorSetter = false;
static TextAttributes convertRawProp(
PropsParserContext const &context,
RawProps const &rawProps,
@@ -192,11 +210,95 @@ BaseTextProps::BaseTextProps(
const PropsParserContext &context,
const BaseTextProps &sourceProps,
const RawProps &rawProps)
: textAttributes(convertRawProp(
context,
rawProps,
sourceProps.textAttributes,
TextAttributes{})){};
: textAttributes(
BaseTextProps::enablePropIteratorSetter
? sourceProps.textAttributes
: convertRawProp(
context,
rawProps,
sourceProps.textAttributes,
TextAttributes{})){};
void BaseTextProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
static auto defaults = TextAttributes{};
switch (hash) {
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, foregroundColor, "color");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontFamily, "fontFamily");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontSize, "fontSize");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
fontSizeMultiplier,
"fontSizeMultiplier");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontWeight, "fontWeight");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontStyle, "fontStyle");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontVariant, "fontVariant");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, allowFontScaling, "allowFontScaling");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, letterSpacing, "letterSpacing");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, textTransform, "textTransform");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, lineHeight, "lineHeight");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, alignment, "textAlign");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
baseWritingDirection,
"baseWritingDirection");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
textDecorationColor,
"textDecorationColor");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
textDecorationLineType,
"textDecorationLine");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
textDecorationStyle,
"textDecorationStyle");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, textShadowOffset, "textShadowOffset");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, textShadowRadius, "textShadowRadius");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, textShadowColor, "textShadowColor");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, isHighlighted, "isHighlighted");
REBUILD_FIELD_SWITCH_CASE(
defaults,
value,
textAttributes,
accessibilityRole,
"accessibilityRole");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, opacity, "opacity");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, backgroundColor, "backgroundColor");
}
}
#pragma mark - DebugStringConvertible
@@ -28,6 +28,14 @@ class BaseTextProps {
const BaseTextProps &sourceProps,
const RawProps &rawProps);
void setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);
static bool enablePropIteratorSetter;
#pragma mark - Props
TextAttributes textAttributes{};
@@ -48,6 +48,18 @@ ParagraphProps::ParagraphProps(
textAttributes.backgroundColor = {};
};
void ParagraphProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
// All Props structs setProp methods must always, unconditionally,
// call all super::setProp methods, since multiple structs may
// reuse the same values.
ViewProps::setProp(context, hash, propName, value);
BaseTextProps::setProp(context, hash, propName, value);
}
#pragma mark - DebugStringConvertible
#if RN_DEBUG_STRING_CONVERTIBLE
@@ -32,6 +32,12 @@ class ParagraphProps : public ViewProps, public BaseTextProps {
ParagraphProps const &sourceProps,
RawProps const &rawProps);
void setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);
#pragma mark - Props
/*
@@ -17,6 +17,15 @@ TextProps::TextProps(
: Props(context, sourceProps, rawProps),
BaseTextProps::BaseTextProps(context, sourceProps, rawProps){};
void TextProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
BaseTextProps::setProp(context, hash, propName, value);
Props::setProp(context, hash, propName, value);
}
#pragma mark - DebugStringConvertible
#if RN_DEBUG_STRING_CONVERTIBLE
@@ -25,6 +25,12 @@ class TextProps : public Props, public BaseTextProps {
const TextProps &sourceProps,
const RawProps &rawProps);
void setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);
#pragma mark - DebugStringConvertible
#if RN_DEBUG_STRING_CONVERTIBLE
@@ -258,6 +258,15 @@ AndroidTextInputProps::AndroidTextInputProps(
hasValue(rawProps, sourceProps.hasPaddingEnd, "End", "padding", "")) {
}
void AndroidTextInputProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
ViewProps::setProp(context, hash, propName, value);
BaseTextProps::setProp(context, hash, propName, value);
}
// TODO T53300085: support this in codegen; this was hand-written
folly::dynamic AndroidTextInputProps::getDynamic() const {
folly::dynamic props = folly::dynamic::object();
@@ -105,6 +105,12 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps {
const AndroidTextInputProps &sourceProps,
const RawProps &rawProps);
void setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);
folly::dynamic getDynamic() const;
#pragma mark - Props
@@ -107,6 +107,15 @@ TextInputProps::TextInputProps(
sourceProps.onChangeSync,
{})){};
void TextInputProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
ViewProps::setProp(context, hash, propName, value);
BaseTextProps::setProp(context, hash, propName, value);
}
TextAttributes TextInputProps::getEffectiveTextAttributes(
Float fontSizeMultiplier) const {
auto result = TextAttributes::defaultTextAttributes();
@@ -31,6 +31,12 @@ class TextInputProps final : public ViewProps, public BaseTextProps {
TextInputProps const &sourceProps,
RawProps const &rawProps);
void setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);
#pragma mark - Props
TextInputTraits const traits{};