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 {
Scanner::Location location;
MessageTemplate::Template message;
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 {
return !binding_pattern_error_.HasError();
return is_valid(BindingPatternProduction);
}
bool is_valid_assignment_pattern() const {
return !assignment_pattern_error_.HasError();
return is_valid(AssignmentPatternProduction);
}
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 {
return !duplicate_formal_parameter_error_.HasError();
return is_valid(DistinctFormalParametersProduction);
}
// Note: callers should also check
// is_valid_formal_parameter_list_without_duplicates().
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()
// and is_valid_formal_parameter_list_without_duplicates().
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_; }
......@@ -583,6 +604,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_expression()) return;
invalid_productions_ |= ExpressionProduction;
expression_error_.location = loc;
expression_error_.message = message;
expression_error_.arg = arg;
......@@ -592,6 +614,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_binding_pattern()) return;
invalid_productions_ |= BindingPatternProduction;
binding_pattern_error_.location = loc;
binding_pattern_error_.message = message;
binding_pattern_error_.arg = arg;
......@@ -601,6 +624,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_assignment_pattern()) return;
invalid_productions_ |= AssignmentPatternProduction;
assignment_pattern_error_.location = loc;
assignment_pattern_error_.message = message;
assignment_pattern_error_.arg = arg;
......@@ -610,6 +634,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_arrow_formal_parameters()) return;
invalid_productions_ |= ArrowFormalParametersProduction;
arrow_formal_parameters_error_.location = loc;
arrow_formal_parameters_error_.message = message;
arrow_formal_parameters_error_.arg = arg;
......@@ -617,6 +642,7 @@ class ParserBase : public Traits {
void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
if (!is_valid_formal_parameter_list_without_duplicates()) return;
invalid_productions_ |= DistinctFormalParametersProduction;
duplicate_formal_parameter_error_.location = loc;
duplicate_formal_parameter_error_.message =
MessageTemplate::kStrictParamDupe;
......@@ -630,6 +656,7 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_strict_mode_formal_parameters()) return;
invalid_productions_ |= StrictModeFormalParametersProduction;
strict_mode_formal_parameter_error_.location = loc;
strict_mode_formal_parameter_error_.message = message;
strict_mode_formal_parameter_error_.arg = arg;
......@@ -639,56 +666,49 @@ class ParserBase : public Traits {
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_strong_mode_formal_parameters()) return;
invalid_productions_ |= StrongModeFormalParametersProduction;
strong_mode_formal_parameter_error_.location = loc;
strong_mode_formal_parameter_error_.message = message;
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,
unsigned productions = StandardProductions) {
if (productions & ExpressionProduction && is_valid_expression()) {
expression_error_ = inner.expression_error_;
}
if (productions & BindingPatternProduction &&
is_valid_binding_pattern()) {
binding_pattern_error_ = inner.binding_pattern_error_;
}
if (productions & AssignmentPatternProduction &&
is_valid_assignment_pattern()) {
assignment_pattern_error_ = inner.assignment_pattern_error_;
}
if (productions & FormalParametersProduction) {
if (is_valid_formal_parameter_list_without_duplicates()) {
// Propagate errors from inner, but don't overwrite already recorded
// errors.
unsigned non_arrow_inner_invalid_productions =
inner.invalid_productions_ & ~ArrowFormalParametersProduction;
if (non_arrow_inner_invalid_productions == 0) return;
unsigned non_arrow_productions =
productions & ~ArrowFormalParametersProduction;
unsigned errors =
non_arrow_productions & non_arrow_inner_invalid_productions;
errors &= ~invalid_productions_;
if (errors != 0) {
invalid_productions_ |= errors;
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_ =
inner.duplicate_formal_parameter_error_;
}
if (is_valid_strict_mode_formal_parameters()) {
if (errors & StrictModeFormalParametersProduction)
strict_mode_formal_parameter_error_ =
inner.strict_mode_formal_parameter_error_;
}
if (is_valid_strong_mode_formal_parameters()) {
if (errors & StrongModeFormalParametersProduction)
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 &&
is_valid_arrow_formal_parameters()) {
// The result continues to be a valid arrow formal parameters if the
// inner expression is a valid binding pattern.
is_valid_arrow_formal_parameters() &&
!inner.is_valid_binding_pattern()) {
invalid_productions_ |= ArrowFormalParametersProduction;
arrow_formal_parameters_error_ = inner.binding_pattern_error_;
}
}
......@@ -706,6 +726,7 @@ class ParserBase : public Traits {
}
private:
unsigned invalid_productions_;
Error expression_error_;
Error binding_pattern_error_;
Error assignment_pattern_error_;
......@@ -2913,7 +2934,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
// "expression" was not itself an arrow function parameter list, but it might
// form part of one. Propagate speculative formal parameter error locations.
classifier->Accumulate(arrow_formals_classifier,
ExpressionClassifier::FormalParametersProduction);
ExpressionClassifier::FormalParametersProductions);
if (!Token::IsAssignmentOp(peek())) {
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