From af1eae9ea313b016f111a25b5252b70aea99aedd Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Wed, 15 Jun 2022 23:37:34 -0700 Subject: [PATCH] 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 --- .../components/text/BaseTextProps.cpp | 112 +++++++++++++++++- .../renderer/components/text/BaseTextProps.h | 8 ++ .../components/text/ParagraphProps.cpp | 12 ++ .../renderer/components/text/ParagraphProps.h | 6 + .../renderer/components/text/TextProps.cpp | 9 ++ .../renderer/components/text/TextProps.h | 6 + .../AndroidTextInputProps.cpp | 9 ++ .../androidtextinput/AndroidTextInputProps.h | 6 + .../textinput/iostextinput/TextInputProps.cpp | 9 ++ .../textinput/iostextinput/TextInputProps.h | 6 + 10 files changed, 178 insertions(+), 5 deletions(-) diff --git a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index a5482e80aa8..e93c000d1b2 100644 --- a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -12,9 +12,27 @@ #include #include +#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 diff --git a/ReactCommon/react/renderer/components/text/BaseTextProps.h b/ReactCommon/react/renderer/components/text/BaseTextProps.h index dea10226dd6..092ff27c963 100644 --- a/ReactCommon/react/renderer/components/text/BaseTextProps.h +++ b/ReactCommon/react/renderer/components/text/BaseTextProps.h @@ -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{}; diff --git a/ReactCommon/react/renderer/components/text/ParagraphProps.cpp b/ReactCommon/react/renderer/components/text/ParagraphProps.cpp index 73de56443cd..6d6f778a70b 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphProps.cpp +++ b/ReactCommon/react/renderer/components/text/ParagraphProps.cpp @@ -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 diff --git a/ReactCommon/react/renderer/components/text/ParagraphProps.h b/ReactCommon/react/renderer/components/text/ParagraphProps.h index 20a5f9edf4a..b73ad0f2a46 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphProps.h +++ b/ReactCommon/react/renderer/components/text/ParagraphProps.h @@ -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 /* diff --git a/ReactCommon/react/renderer/components/text/TextProps.cpp b/ReactCommon/react/renderer/components/text/TextProps.cpp index e2d9ac54168..a8b83aa0b1b 100644 --- a/ReactCommon/react/renderer/components/text/TextProps.cpp +++ b/ReactCommon/react/renderer/components/text/TextProps.cpp @@ -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 diff --git a/ReactCommon/react/renderer/components/text/TextProps.h b/ReactCommon/react/renderer/components/text/TextProps.h index 64eb66c6af0..53df63702b1 100644 --- a/ReactCommon/react/renderer/components/text/TextProps.h +++ b/ReactCommon/react/renderer/components/text/TextProps.h @@ -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 diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index 1075179f1a2..becfec590be 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -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(); diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h index aad4572bd41..6843425b190 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -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 diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp index a8716286aee..96d4d0c1849 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp @@ -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(); diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h index a72b63063b9..bede7451767 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h @@ -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{};