Commit 5e1862fe authored by wingo's avatar wingo Committed by Commit bot

Speed up ExpressionClassifier::Accumulate

The following changeset introduced a regression on CodeLoad of about 3%:

  https://chromium.googlesource.com/v8/v8/+/e73594c7fb3e6b5834b7ddfe78727fb994bab25f

This CL should reduce the regression to 1.5%.

R=dslomov@chromium.org
LOG=N
BUG=

Review URL: https://codereview.chromium.org/1163323006

Cr-Commit-Position: refs/heads/master@{#28872}
parent 5f1f7c15
...@@ -517,40 +517,61 @@ class ParserBase : public Traits { ...@@ -517,40 +517,61 @@ class ParserBase : public Traits {
Scanner::Location location; Scanner::Location location;
MessageTemplate::Template message; MessageTemplate::Template message;
const char* arg; const char* arg;
};
enum TargetProduction {
ExpressionProduction = 1 << 0,
BindingPatternProduction = 1 << 1,
AssignmentPatternProduction = 1 << 2,
DistinctFormalParametersProduction = 1 << 3,
StrictModeFormalParametersProduction = 1 << 4,
StrongModeFormalParametersProduction = 1 << 5,
ArrowFormalParametersProduction = 1 << 6,
bool HasError() const { return location.IsValid(); } PatternProductions =
(BindingPatternProduction | AssignmentPatternProduction),
FormalParametersProductions = (DistinctFormalParametersProduction |
StrictModeFormalParametersProduction |
StrongModeFormalParametersProduction),
StandardProductions = ExpressionProduction | PatternProductions,
AllProductions = (StandardProductions | FormalParametersProductions |
ArrowFormalParametersProduction)
}; };
ExpressionClassifier() {} ExpressionClassifier() : invalid_productions_(0) {}
bool is_valid(unsigned productions) const {
return (invalid_productions_ & productions) == 0;
}
bool is_valid_expression() const { return !expression_error_.HasError(); } bool is_valid_expression() const { return is_valid(ExpressionProduction); }
bool is_valid_binding_pattern() const { bool is_valid_binding_pattern() const {
return !binding_pattern_error_.HasError(); return is_valid(BindingPatternProduction);
} }
bool is_valid_assignment_pattern() const { bool is_valid_assignment_pattern() const {
return !assignment_pattern_error_.HasError(); return is_valid(AssignmentPatternProduction);
} }
bool is_valid_arrow_formal_parameters() const { bool is_valid_arrow_formal_parameters() const {
return !arrow_formal_parameters_error_.HasError(); return is_valid(ArrowFormalParametersProduction);
} }
bool is_valid_formal_parameter_list_without_duplicates() const { bool is_valid_formal_parameter_list_without_duplicates() const {
return !duplicate_formal_parameter_error_.HasError(); return is_valid(DistinctFormalParametersProduction);
} }
// Note: callers should also check // Note: callers should also check
// is_valid_formal_parameter_list_without_duplicates(). // is_valid_formal_parameter_list_without_duplicates().
bool is_valid_strict_mode_formal_parameters() const { bool is_valid_strict_mode_formal_parameters() const {
return !strict_mode_formal_parameter_error_.HasError(); return is_valid(StrictModeFormalParametersProduction);
} }
// Note: callers should also check is_valid_strict_mode_formal_parameters() // Note: callers should also check is_valid_strict_mode_formal_parameters()
// and is_valid_formal_parameter_list_without_duplicates(). // and is_valid_formal_parameter_list_without_duplicates().
bool is_valid_strong_mode_formal_parameters() const { bool is_valid_strong_mode_formal_parameters() const {
return !strong_mode_formal_parameter_error_.HasError(); return is_valid(StrongModeFormalParametersProduction);
} }
const Error& expression_error() const { return expression_error_; } const Error& expression_error() const { return expression_error_; }
...@@ -583,6 +604,7 @@ class ParserBase : public Traits { ...@@ -583,6 +604,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_expression()) return; if (!is_valid_expression()) return;
invalid_productions_ |= ExpressionProduction;
expression_error_.location = loc; expression_error_.location = loc;
expression_error_.message = message; expression_error_.message = message;
expression_error_.arg = arg; expression_error_.arg = arg;
...@@ -592,6 +614,7 @@ class ParserBase : public Traits { ...@@ -592,6 +614,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_binding_pattern()) return; if (!is_valid_binding_pattern()) return;
invalid_productions_ |= BindingPatternProduction;
binding_pattern_error_.location = loc; binding_pattern_error_.location = loc;
binding_pattern_error_.message = message; binding_pattern_error_.message = message;
binding_pattern_error_.arg = arg; binding_pattern_error_.arg = arg;
...@@ -601,6 +624,7 @@ class ParserBase : public Traits { ...@@ -601,6 +624,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_assignment_pattern()) return; if (!is_valid_assignment_pattern()) return;
invalid_productions_ |= AssignmentPatternProduction;
assignment_pattern_error_.location = loc; assignment_pattern_error_.location = loc;
assignment_pattern_error_.message = message; assignment_pattern_error_.message = message;
assignment_pattern_error_.arg = arg; assignment_pattern_error_.arg = arg;
...@@ -610,6 +634,7 @@ class ParserBase : public Traits { ...@@ -610,6 +634,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_arrow_formal_parameters()) return; if (!is_valid_arrow_formal_parameters()) return;
invalid_productions_ |= ArrowFormalParametersProduction;
arrow_formal_parameters_error_.location = loc; arrow_formal_parameters_error_.location = loc;
arrow_formal_parameters_error_.message = message; arrow_formal_parameters_error_.message = message;
arrow_formal_parameters_error_.arg = arg; arrow_formal_parameters_error_.arg = arg;
...@@ -617,6 +642,7 @@ class ParserBase : public Traits { ...@@ -617,6 +642,7 @@ class ParserBase : public Traits {
void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
if (!is_valid_formal_parameter_list_without_duplicates()) return; if (!is_valid_formal_parameter_list_without_duplicates()) return;
invalid_productions_ |= DistinctFormalParametersProduction;
duplicate_formal_parameter_error_.location = loc; duplicate_formal_parameter_error_.location = loc;
duplicate_formal_parameter_error_.message = duplicate_formal_parameter_error_.message =
MessageTemplate::kStrictParamDupe; MessageTemplate::kStrictParamDupe;
...@@ -630,6 +656,7 @@ class ParserBase : public Traits { ...@@ -630,6 +656,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_strict_mode_formal_parameters()) return; if (!is_valid_strict_mode_formal_parameters()) return;
invalid_productions_ |= StrictModeFormalParametersProduction;
strict_mode_formal_parameter_error_.location = loc; strict_mode_formal_parameter_error_.location = loc;
strict_mode_formal_parameter_error_.message = message; strict_mode_formal_parameter_error_.message = message;
strict_mode_formal_parameter_error_.arg = arg; strict_mode_formal_parameter_error_.arg = arg;
...@@ -639,56 +666,49 @@ class ParserBase : public Traits { ...@@ -639,56 +666,49 @@ class ParserBase : public Traits {
MessageTemplate::Template message, MessageTemplate::Template message,
const char* arg = nullptr) { const char* arg = nullptr) {
if (!is_valid_strong_mode_formal_parameters()) return; if (!is_valid_strong_mode_formal_parameters()) return;
invalid_productions_ |= StrongModeFormalParametersProduction;
strong_mode_formal_parameter_error_.location = loc; strong_mode_formal_parameter_error_.location = loc;
strong_mode_formal_parameter_error_.message = message; strong_mode_formal_parameter_error_.message = message;
strong_mode_formal_parameter_error_.arg = arg; strong_mode_formal_parameter_error_.arg = arg;
} }
enum TargetProduction {
ExpressionProduction = 1 << 0,
BindingPatternProduction = 1 << 1,
AssignmentPatternProduction = 1 << 2,
FormalParametersProduction = 1 << 3,
ArrowFormalParametersProduction = 1 << 4,
StandardProductions = (ExpressionProduction | BindingPatternProduction |
AssignmentPatternProduction),
PatternProductions =
BindingPatternProduction | AssignmentPatternProduction,
AllProductions = (StandardProductions | FormalParametersProduction |
ArrowFormalParametersProduction),
};
void Accumulate(const ExpressionClassifier& inner, void Accumulate(const ExpressionClassifier& inner,
unsigned productions = StandardProductions) { unsigned productions = StandardProductions) {
if (productions & ExpressionProduction && is_valid_expression()) { // Propagate errors from inner, but don't overwrite already recorded
expression_error_ = inner.expression_error_; // errors.
} unsigned non_arrow_inner_invalid_productions =
if (productions & BindingPatternProduction && inner.invalid_productions_ & ~ArrowFormalParametersProduction;
is_valid_binding_pattern()) { if (non_arrow_inner_invalid_productions == 0) return;
binding_pattern_error_ = inner.binding_pattern_error_; unsigned non_arrow_productions =
} productions & ~ArrowFormalParametersProduction;
if (productions & AssignmentPatternProduction && unsigned errors =
is_valid_assignment_pattern()) { non_arrow_productions & non_arrow_inner_invalid_productions;
assignment_pattern_error_ = inner.assignment_pattern_error_; errors &= ~invalid_productions_;
} if (errors != 0) {
if (productions & FormalParametersProduction) { invalid_productions_ |= errors;
if (is_valid_formal_parameter_list_without_duplicates()) { if (errors & ExpressionProduction)
expression_error_ = inner.expression_error_;
if (errors & BindingPatternProduction)
binding_pattern_error_ = inner.binding_pattern_error_;
if (errors & AssignmentPatternProduction)
assignment_pattern_error_ = inner.assignment_pattern_error_;
if (errors & DistinctFormalParametersProduction)
duplicate_formal_parameter_error_ = duplicate_formal_parameter_error_ =
inner.duplicate_formal_parameter_error_; inner.duplicate_formal_parameter_error_;
} if (errors & StrictModeFormalParametersProduction)
if (is_valid_strict_mode_formal_parameters()) {
strict_mode_formal_parameter_error_ = strict_mode_formal_parameter_error_ =
inner.strict_mode_formal_parameter_error_; inner.strict_mode_formal_parameter_error_;
} if (errors & StrongModeFormalParametersProduction)
if (is_valid_strong_mode_formal_parameters()) {
strong_mode_formal_parameter_error_ = strong_mode_formal_parameter_error_ =
inner.strong_mode_formal_parameter_error_; inner.strong_mode_formal_parameter_error_;
}
} }
// As an exception to the above, the result continues to be a valid arrow
// formal parameters if the inner expression is a valid binding pattern.
if (productions & ArrowFormalParametersProduction && if (productions & ArrowFormalParametersProduction &&
is_valid_arrow_formal_parameters()) { is_valid_arrow_formal_parameters() &&
// The result continues to be a valid arrow formal parameters if the !inner.is_valid_binding_pattern()) {
// inner expression is a valid binding pattern. invalid_productions_ |= ArrowFormalParametersProduction;
arrow_formal_parameters_error_ = inner.binding_pattern_error_; arrow_formal_parameters_error_ = inner.binding_pattern_error_;
} }
} }
...@@ -706,6 +726,7 @@ class ParserBase : public Traits { ...@@ -706,6 +726,7 @@ class ParserBase : public Traits {
} }
private: private:
unsigned invalid_productions_;
Error expression_error_; Error expression_error_;
Error binding_pattern_error_; Error binding_pattern_error_;
Error assignment_pattern_error_; Error assignment_pattern_error_;
...@@ -2913,7 +2934,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, ...@@ -2913,7 +2934,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
// "expression" was not itself an arrow function parameter list, but it might // "expression" was not itself an arrow function parameter list, but it might
// form part of one. Propagate speculative formal parameter error locations. // form part of one. Propagate speculative formal parameter error locations.
classifier->Accumulate(arrow_formals_classifier, classifier->Accumulate(arrow_formals_classifier,
ExpressionClassifier::FormalParametersProduction); ExpressionClassifier::FormalParametersProductions);
if (!Token::IsAssignmentOp(peek())) { if (!Token::IsAssignmentOp(peek())) {
if (fni_ != NULL) fni_->Leave(); if (fni_ != NULL) fni_->Leave();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment