Ignore:
Timestamp:
May 31, 2016, 1:57:20 PM (9 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Recover parser performance regression by async support
https://bugs.webkit.org/show_bug.cgi?id=158228

Reviewed by Saam Barati.

This patch recovers parser performance regression caused in r201481.

Compared to the version that reverts r201481, still ~1% regression remains.
But compared to ToT, this patch significantly improves the code-load performance.

In Linux x64 JSCOnly port, with GCC 5.3.1.

reverted v.s. patched.

reverted patched

closure 0.61805+-0.00376 ? 0.62280+-0.00525 ?
jquery 8.03778+-0.02114 8.03453+-0.04646

<geometric> 2.22883+-0.00836 ? 2.23688+-0.00995 ? might be 1.0036x slower

ToT v.s. patched.

baseline patched

closure 0.65490+-0.00351 0.62473+-0.00363 definitely 1.0483x faster
jquery 8.25373+-0.06256 8.04701+-0.03455 definitely 1.0257x faster

<geometric> 2.32488+-0.00921 2.24210+-0.00592 definitely 1.0369x faster

  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):

  • bytecode/UnlinkedFunctionExecutable.h:

Extend SourceParseMode.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::isArrowFunctionParameters):
Do not call matchSpecIdentifier() as much as we can. This greatly improves the performance.

(JSC::Parser<LexerType>::parseStatementListItem):
(JSC::Parser<LexerType>::parseStatement):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
Do not touch currentScope()->isGenerator() even if it is unnecessary in parseFunctionInfo.
And accidental syntaxChecker => context changes are fixed.

(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseExpressionOrLabelStatement):
(JSC::Parser<LexerType>::parseImportClauseItem):
(JSC::Parser<LexerType>::parseExportDeclaration):
(JSC::Parser<LexerType>::parseAssignmentExpression):
Do not use matchSpecIdentifier() in the hot paths.

(JSC::Parser<LexerType>::parseProperty):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::parseUnaryExpression):
(JSC::Parser<LexerType>::printUnexpectedTokenText): Deleted.

  • parser/Parser.h:

(JSC::isIdentifierOrKeyword):
AWAIT shoud be one of the keywords. This AWAIT check is unnecessary.

(JSC::Parser::upperScope):
(JSC::Parser::matchSpecIdentifier):
Touching currentScope() and its member causes significant performance degradation.
We carefully remove the above access in the hot paths.

(JSC::Parser::isDisallowedIdentifierAwait):

  • parser/ParserModes.h:

(JSC::SourceParseModeSet::SourceParseModeSet):
(JSC::SourceParseModeSet::contains):
(JSC::SourceParseModeSet::mergeSourceParseModes):
(JSC::isFunctionParseMode):
(JSC::isAsyncFunctionParseMode):
(JSC::isAsyncArrowFunctionParseMode):
(JSC::isAsyncFunctionWrapperParseMode):
(JSC::isAsyncFunctionBodyParseMode):
(JSC::isModuleParseMode):
(JSC::isProgramParseMode):
(JSC::constructAbilityForParseMode):
The parser frequently checks SourceParseMode. And variety of SourceParseMode becomes many.
So using switch onto SourceParseMode degrades the performance. Instead, we use bit tests to guard against
many SourceParseModes. We expect that this will be efficiently compiled into test & jmp.

  • parser/ParserTokens.h:

Change AWAIT to one of the keywords, as the same to YIELD / LET.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/ParserModes.h

    r201481 r201523  
    4444enum class FunctionMode { FunctionExpression, FunctionDeclaration, MethodDefinition };
    4545
    46 enum class SourceParseMode : uint8_t {
    47     NormalFunctionMode,
    48     GeneratorBodyMode,
    49     GeneratorWrapperFunctionMode,
    50     GetterMode,
    51     SetterMode,
    52     MethodMode,
    53     ArrowFunctionMode,
    54     AsyncFunctionBodyMode,
    55     AsyncArrowFunctionBodyMode,
    56     AsyncFunctionMode,
    57     AsyncMethodMode,
    58     AsyncArrowFunctionMode,
    59     ProgramMode,
    60     ModuleAnalyzeMode,
    61     ModuleEvaluateMode
     46// When you add a new source parse mode, do not forget to ensure that the predicates defined in this
     47// file work with the newly added mode.
     48enum class SourceParseMode : uint16_t {
     49    NormalFunctionMode            = 0b0000000000000001,
     50    GeneratorBodyMode             = 0b0000000000000010,
     51    GeneratorWrapperFunctionMode  = 0b0000000000000100,
     52    GetterMode                    = 0b0000000000001000,
     53    SetterMode                    = 0b0000000000010000,
     54    MethodMode                    = 0b0000000000100000,
     55    ArrowFunctionMode             = 0b0000000001000000,
     56    AsyncFunctionBodyMode         = 0b0000000010000000,
     57    AsyncArrowFunctionBodyMode    = 0b0000000100000000,
     58    AsyncFunctionMode             = 0b0000001000000000,
     59    AsyncMethodMode               = 0b0000010000000000,
     60    AsyncArrowFunctionMode        = 0b0000100000000000,
     61    ProgramMode                   = 0b0001000000000000,
     62    ModuleAnalyzeMode             = 0b0010000000000000,
     63    ModuleEvaluateMode            = 0b0100000000000000,
    6264};
    6365
    64 inline bool isFunctionParseMode(SourceParseMode parseMode)
    65 {
    66     switch (parseMode) {
    67     case SourceParseMode::NormalFunctionMode:
    68     case SourceParseMode::GeneratorBodyMode:
    69     case SourceParseMode::GeneratorWrapperFunctionMode:
    70     case SourceParseMode::GetterMode:
    71     case SourceParseMode::SetterMode:
    72     case SourceParseMode::MethodMode:
    73     case SourceParseMode::ArrowFunctionMode:
    74     case SourceParseMode::AsyncFunctionBodyMode:
    75     case SourceParseMode::AsyncFunctionMode:
    76     case SourceParseMode::AsyncMethodMode:
    77     case SourceParseMode::AsyncArrowFunctionMode:
    78     case SourceParseMode::AsyncArrowFunctionBodyMode:
    79         return true;
    80 
    81     case SourceParseMode::ProgramMode:
    82     case SourceParseMode::ModuleAnalyzeMode:
    83     case SourceParseMode::ModuleEvaluateMode:
    84         return false;
    85     }
    86     RELEASE_ASSERT_NOT_REACHED();
    87     return false;
    88 }
    89 
    90 inline bool isAsyncFunctionParseMode(SourceParseMode parseMode)
    91 {
    92     switch (parseMode) {
    93     case SourceParseMode::AsyncFunctionBodyMode:
    94     case SourceParseMode::AsyncArrowFunctionBodyMode:
    95     case SourceParseMode::AsyncFunctionMode:
    96     case SourceParseMode::AsyncMethodMode:
    97     case SourceParseMode::AsyncArrowFunctionMode:
    98         return true;
    99 
    100     case SourceParseMode::NormalFunctionMode:
    101     case SourceParseMode::GeneratorBodyMode:
    102     case SourceParseMode::GeneratorWrapperFunctionMode:
    103     case SourceParseMode::GetterMode:
    104     case SourceParseMode::SetterMode:
    105     case SourceParseMode::MethodMode:
    106     case SourceParseMode::ArrowFunctionMode:
    107     case SourceParseMode::ModuleAnalyzeMode:
    108     case SourceParseMode::ModuleEvaluateMode:
    109     case SourceParseMode::ProgramMode:
    110         return false;
    111     }
    112     RELEASE_ASSERT_NOT_REACHED();
    113     return false;
    114 }
    115 
    116 inline bool isAsyncArrowFunctionParseMode(SourceParseMode parseMode)
    117 {
    118     switch (parseMode) {
    119     case SourceParseMode::AsyncArrowFunctionMode:
    120     case SourceParseMode::AsyncArrowFunctionBodyMode:
    121         return true;
    122 
    123     case SourceParseMode::NormalFunctionMode:
    124     case SourceParseMode::GeneratorBodyMode:
    125     case SourceParseMode::GeneratorWrapperFunctionMode:
    126     case SourceParseMode::GetterMode:
    127     case SourceParseMode::SetterMode:
    128     case SourceParseMode::MethodMode:
    129     case SourceParseMode::ArrowFunctionMode:
    130     case SourceParseMode::ModuleAnalyzeMode:
    131     case SourceParseMode::ModuleEvaluateMode:
    132     case SourceParseMode::AsyncFunctionBodyMode:
    133     case SourceParseMode::AsyncMethodMode:
    134     case SourceParseMode::AsyncFunctionMode:
    135     case SourceParseMode::ProgramMode:
    136         return false;
    137     }
    138 
    139     RELEASE_ASSERT_NOT_REACHED();
    140     return false;
    141 }
    142 
    143 inline bool isAsyncFunctionWrapperParseMode(SourceParseMode parseMode)
    144 {
    145     switch (parseMode) {
    146     case SourceParseMode::AsyncFunctionMode:
    147     case SourceParseMode::AsyncMethodMode:
    148     case SourceParseMode::AsyncArrowFunctionMode:
    149         return true;
    150 
    151     case SourceParseMode::AsyncFunctionBodyMode:
    152     case SourceParseMode::AsyncArrowFunctionBodyMode:
    153     case SourceParseMode::NormalFunctionMode:
    154     case SourceParseMode::GeneratorBodyMode:
    155     case SourceParseMode::GeneratorWrapperFunctionMode:
    156     case SourceParseMode::GetterMode:
    157     case SourceParseMode::SetterMode:
    158     case SourceParseMode::MethodMode:
    159     case SourceParseMode::ArrowFunctionMode:
    160     case SourceParseMode::ModuleAnalyzeMode:
    161     case SourceParseMode::ModuleEvaluateMode:
    162     case SourceParseMode::ProgramMode:
    163         return false;
    164     }
    165     RELEASE_ASSERT_NOT_REACHED();
    166     return false;
    167 }
    168 
    169 inline bool isAsyncFunctionBodyParseMode(SourceParseMode parseMode)
    170 {
    171     switch (parseMode) {
    172     case SourceParseMode::AsyncFunctionBodyMode:
    173     case SourceParseMode::AsyncArrowFunctionBodyMode:
    174         return true;
    175 
    176     case SourceParseMode::NormalFunctionMode:
    177     case SourceParseMode::GeneratorBodyMode:
    178     case SourceParseMode::GeneratorWrapperFunctionMode:
    179     case SourceParseMode::GetterMode:
    180     case SourceParseMode::SetterMode:
    181     case SourceParseMode::MethodMode:
    182     case SourceParseMode::ArrowFunctionMode:
    183     case SourceParseMode::AsyncFunctionMode:
    184     case SourceParseMode::AsyncMethodMode:
    185     case SourceParseMode::AsyncArrowFunctionMode:
    186     case SourceParseMode::ModuleAnalyzeMode:
    187     case SourceParseMode::ModuleEvaluateMode:
    188     case SourceParseMode::ProgramMode:
    189         return false;
    190     }
    191     RELEASE_ASSERT_NOT_REACHED();
    192     return false;
    193 }
    194 
    195 inline bool isModuleParseMode(SourceParseMode parseMode)
    196 {
    197     switch (parseMode) {
    198     case SourceParseMode::ModuleAnalyzeMode:
    199     case SourceParseMode::ModuleEvaluateMode:
    200         return true;
    201 
    202     case SourceParseMode::NormalFunctionMode:
    203     case SourceParseMode::GeneratorBodyMode:
    204     case SourceParseMode::GeneratorWrapperFunctionMode:
    205     case SourceParseMode::GetterMode:
    206     case SourceParseMode::SetterMode:
    207     case SourceParseMode::MethodMode:
    208     case SourceParseMode::ArrowFunctionMode:
    209     case SourceParseMode::AsyncFunctionBodyMode:
    210     case SourceParseMode::AsyncFunctionMode:
    211     case SourceParseMode::AsyncMethodMode:
    212     case SourceParseMode::AsyncArrowFunctionMode:
    213     case SourceParseMode::AsyncArrowFunctionBodyMode:
    214     case SourceParseMode::ProgramMode:
    215         return false;
    216     }
    217     RELEASE_ASSERT_NOT_REACHED();
    218     return false;
    219 }
    220 
    221 inline bool isProgramParseMode(SourceParseMode parseMode)
    222 {
    223     switch (parseMode) {
    224     case SourceParseMode::ProgramMode:
    225         return true;
    226 
    227     case SourceParseMode::NormalFunctionMode:
    228     case SourceParseMode::GeneratorBodyMode:
    229     case SourceParseMode::GeneratorWrapperFunctionMode:
    230     case SourceParseMode::GetterMode:
    231     case SourceParseMode::SetterMode:
    232     case SourceParseMode::MethodMode:
    233     case SourceParseMode::ArrowFunctionMode:
    234     case SourceParseMode::AsyncFunctionBodyMode:
    235     case SourceParseMode::AsyncFunctionMode:
    236     case SourceParseMode::AsyncMethodMode:
    237     case SourceParseMode::AsyncArrowFunctionMode:
    238     case SourceParseMode::AsyncArrowFunctionBodyMode:
    239     case SourceParseMode::ModuleAnalyzeMode:
    240     case SourceParseMode::ModuleEvaluateMode:
    241         return false;
    242     }
    243     RELEASE_ASSERT_NOT_REACHED();
    244     return false;
    245 }
    246 
    247 inline ConstructAbility constructAbilityForParseMode(SourceParseMode parseMode)
    248 {
    249     switch (parseMode) {
    250     case SourceParseMode::NormalFunctionMode:
     66class SourceParseModeSet {
     67public:
     68    template<typename... Modes>
     69    SourceParseModeSet(Modes... args)
     70        : m_mask(mergeSourceParseModes(args...))
     71    {
     72    }
     73
     74    ALWAYS_INLINE bool contains(SourceParseMode mode)
     75    {
     76        return static_cast<unsigned>(mode) & m_mask;
     77    }
     78
     79private:
     80    ALWAYS_INLINE static unsigned mergeSourceParseModes(SourceParseMode mode)
     81    {
     82        return static_cast<unsigned>(mode);
     83    }
     84
     85    template<typename... Rest>
     86    ALWAYS_INLINE static unsigned mergeSourceParseModes(SourceParseMode mode, Rest... rest)
     87    {
     88        return static_cast<unsigned>(mode) | mergeSourceParseModes(rest...);
     89    }
     90
     91    const unsigned m_mask;
     92};
     93
     94ALWAYS_INLINE bool isFunctionParseMode(SourceParseMode parseMode)
     95{
     96    return SourceParseModeSet(
     97        SourceParseMode::NormalFunctionMode,
     98        SourceParseMode::GeneratorBodyMode,
     99        SourceParseMode::GeneratorWrapperFunctionMode,
     100        SourceParseMode::GetterMode,
     101        SourceParseMode::SetterMode,
     102        SourceParseMode::MethodMode,
     103        SourceParseMode::ArrowFunctionMode,
     104        SourceParseMode::AsyncFunctionBodyMode,
     105        SourceParseMode::AsyncFunctionMode,
     106        SourceParseMode::AsyncMethodMode,
     107        SourceParseMode::AsyncArrowFunctionMode,
     108        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     109}
     110
     111ALWAYS_INLINE bool isAsyncFunctionParseMode(SourceParseMode parseMode)
     112{
     113    return SourceParseModeSet(
     114        SourceParseMode::AsyncFunctionBodyMode,
     115        SourceParseMode::AsyncFunctionMode,
     116        SourceParseMode::AsyncMethodMode,
     117        SourceParseMode::AsyncArrowFunctionMode,
     118        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     119}
     120
     121ALWAYS_INLINE bool isAsyncArrowFunctionParseMode(SourceParseMode parseMode)
     122{
     123    return SourceParseModeSet(
     124        SourceParseMode::AsyncArrowFunctionMode,
     125        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     126}
     127
     128ALWAYS_INLINE bool isAsyncFunctionWrapperParseMode(SourceParseMode parseMode)
     129{
     130    return SourceParseModeSet(
     131        SourceParseMode::AsyncArrowFunctionMode,
     132        SourceParseMode::AsyncFunctionMode,
     133        SourceParseMode::AsyncMethodMode).contains(parseMode);
     134}
     135
     136ALWAYS_INLINE bool isAsyncFunctionBodyParseMode(SourceParseMode parseMode)
     137{
     138    return SourceParseModeSet(
     139        SourceParseMode::AsyncFunctionBodyMode,
     140        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     141}
     142
     143ALWAYS_INLINE bool isModuleParseMode(SourceParseMode parseMode)
     144{
     145    return SourceParseModeSet(
     146        SourceParseMode::ModuleAnalyzeMode,
     147        SourceParseMode::ModuleEvaluateMode).contains(parseMode);
     148}
     149
     150ALWAYS_INLINE bool isProgramParseMode(SourceParseMode parseMode)
     151{
     152    return SourceParseModeSet(SourceParseMode::ProgramMode).contains(parseMode);
     153}
     154
     155ALWAYS_INLINE ConstructAbility constructAbilityForParseMode(SourceParseMode parseMode)
     156{
     157    if (parseMode == SourceParseMode::NormalFunctionMode)
    251158        return ConstructAbility::CanConstruct;
    252 
    253     case SourceParseMode::GeneratorBodyMode:
    254     case SourceParseMode::GeneratorWrapperFunctionMode:
    255     case SourceParseMode::GetterMode:
    256     case SourceParseMode::SetterMode:
    257     case SourceParseMode::MethodMode:
    258     case SourceParseMode::ArrowFunctionMode:
    259     case SourceParseMode::AsyncFunctionBodyMode:
    260     case SourceParseMode::AsyncArrowFunctionBodyMode:
    261     case SourceParseMode::AsyncFunctionMode:
    262     case SourceParseMode::AsyncMethodMode:
    263     case SourceParseMode::AsyncArrowFunctionMode:
    264         return ConstructAbility::CannotConstruct;
    265 
    266     case SourceParseMode::ProgramMode:
    267     case SourceParseMode::ModuleAnalyzeMode:
    268     case SourceParseMode::ModuleEvaluateMode:
    269         break;
    270     }
    271     RELEASE_ASSERT_NOT_REACHED();
    272     return ConstructAbility::CanConstruct;
     159    return ConstructAbility::CannotConstruct;
    273160}
    274161
Note: See TracChangeset for help on using the changeset viewer.