Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(923)

Unified Diff: src/parsing/expression-classifier.h

Issue 1708193003: Reduce the memory footprint of expression classifiers (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/parsing/parser.h » ('j') | src/parsing/parser-base.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/expression-classifier.h
diff --git a/src/parsing/expression-classifier.h b/src/parsing/expression-classifier.h
index fa1a2f97a486895482bcc6e88b851f8331347131..5640d689fbfa09ccc49c6c5a1e23a9b32029446a 100644
--- a/src/parsing/expression-classifier.h
+++ b/src/parsing/expression-classifier.h
@@ -13,33 +13,53 @@ namespace v8 {
namespace internal {
+#define ERROR_CODES(T) \
+ T(ExpressionProduction, 0) \
+ T(FormalParameterInitializerProduction, 1) \
+ T(BindingPatternProduction, 2) \
+ T(AssignmentPatternProduction, 3) \
+ T(DistinctFormalParametersProduction, 4) \
+ T(StrictModeFormalParametersProduction, 5) \
+ T(StrongModeFormalParametersProduction, 6) \
caitp (gmail) 2016/02/18 16:50:22 I feel like we could probably just take this oppor
nickie 2016/02/19 08:56:31 I assumed strong mode removal would be an independ
+ T(ArrowFormalParametersProduction, 7) \
+ T(LetPatternProduction, 8) \
+ T(CoverInitializedNameProduction, 9)
+
+
template <typename Traits>
class ExpressionClassifier {
public:
+ enum ErrorKind : unsigned {
+#define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE,
+ ERROR_CODES(DEFINE_ERROR_KIND)
+#undef DEFINE_ERROR_KIND
+ kUnusedError = 15 // Larger than error codes; should fit in 4 bits
+ };
+
struct Error {
- Error()
+ V8_INLINE Error()
: location(Scanner::Location::invalid()),
message(MessageTemplate::kNone),
+ kind(kUnusedError),
type(kSyntaxError),
arg(nullptr) {}
+ V8_INLINE explicit Error(Scanner::Location loc,
+ MessageTemplate::Template msg, ErrorKind k,
+ const char* a = nullptr,
+ ParseErrorType t = kSyntaxError)
+ : location(loc), message(msg), kind(k), type(t), arg(a) {}
Scanner::Location location;
- MessageTemplate::Template message : 30;
+ MessageTemplate::Template message : 26;
+ ErrorKind kind : 4;
ParseErrorType type : 2;
const char* arg;
};
- enum TargetProduction {
- ExpressionProduction = 1 << 0,
- FormalParameterInitializerProduction = 1 << 1,
- BindingPatternProduction = 1 << 2,
- AssignmentPatternProduction = 1 << 3,
- DistinctFormalParametersProduction = 1 << 4,
- StrictModeFormalParametersProduction = 1 << 5,
- StrongModeFormalParametersProduction = 1 << 6,
- ArrowFormalParametersProduction = 1 << 7,
- LetPatternProduction = 1 << 8,
- CoverInitializedNameProduction = 1 << 9,
+ enum TargetProduction : unsigned {
+#define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE,
+ ERROR_CODES(DEFINE_PRODUCTION)
+#undef DEFINE_PRODUCTION
ExpressionProductions =
(ExpressionProduction | FormalParameterInitializerProduction),
@@ -54,14 +74,18 @@ class ExpressionClassifier {
ArrowFormalParametersProduction | CoverInitializedNameProduction)
};
- enum FunctionProperties { NonSimpleParameter = 1 << 0 };
+ enum FunctionProperties : unsigned {
+ NonSimpleParameter = 1 << 0
+ };
explicit ExpressionClassifier(const Traits* t)
: zone_(t->zone()),
non_patterns_to_rewrite_(t->GetNonPatternList()),
invalid_productions_(0),
function_properties_(0),
+ reported_errors_(t->GetReportedErrorList()),
duplicate_finder_(nullptr) {
+ reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
non_pattern_begin_ = non_patterns_to_rewrite_->length();
}
@@ -70,96 +94,111 @@ class ExpressionClassifier {
non_patterns_to_rewrite_(t->GetNonPatternList()),
invalid_productions_(0),
function_properties_(0),
+ reported_errors_(t->GetReportedErrorList()),
duplicate_finder_(duplicate_finder) {
+ reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
non_pattern_begin_ = non_patterns_to_rewrite_->length();
}
~ExpressionClassifier() { Discard(); }
- bool is_valid(unsigned productions) const {
+ V8_INLINE bool is_valid(unsigned productions) const {
return (invalid_productions_ & productions) == 0;
}
- DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
+ V8_INLINE DuplicateFinder* duplicate_finder() const {
+ return duplicate_finder_;
+ }
- bool is_valid_expression() const { return is_valid(ExpressionProduction); }
+ V8_INLINE bool is_valid_expression() const {
+ return is_valid(ExpressionProduction);
+ }
- bool is_valid_formal_parameter_initializer() const {
+ V8_INLINE bool is_valid_formal_parameter_initializer() const {
return is_valid(FormalParameterInitializerProduction);
}
- bool is_valid_binding_pattern() const {
+ V8_INLINE bool is_valid_binding_pattern() const {
return is_valid(BindingPatternProduction);
}
- bool is_valid_assignment_pattern() const {
+ V8_INLINE bool is_valid_assignment_pattern() const {
return is_valid(AssignmentPatternProduction);
}
- bool is_valid_arrow_formal_parameters() const {
+ V8_INLINE bool is_valid_arrow_formal_parameters() const {
return is_valid(ArrowFormalParametersProduction);
}
- bool is_valid_formal_parameter_list_without_duplicates() const {
+ V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const {
return is_valid(DistinctFormalParametersProduction);
}
// Note: callers should also check
// is_valid_formal_parameter_list_without_duplicates().
- bool is_valid_strict_mode_formal_parameters() const {
+ V8_INLINE bool is_valid_strict_mode_formal_parameters() const {
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 {
+ V8_INLINE bool is_valid_strong_mode_formal_parameters() const {
return is_valid(StrongModeFormalParametersProduction);
}
- bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
+ V8_INLINE bool is_valid_let_pattern() const {
+ return is_valid(LetPatternProduction);
+ }
- const Error& expression_error() const { return expression_error_; }
+ V8_INLINE const Error& expression_error() const {
+ return reported_error(kExpressionProduction);
+ }
- const Error& formal_parameter_initializer_error() const {
- return formal_parameter_initializer_error_;
+ V8_INLINE const Error& formal_parameter_initializer_error() const {
+ return reported_error(kFormalParameterInitializerProduction);
}
- const Error& binding_pattern_error() const { return binding_pattern_error_; }
+ V8_INLINE const Error& binding_pattern_error() const {
caitp (gmail) 2016/02/18 16:57:47 maybe if you added like a `accessor_name` paramete
nickie 2016/02/19 08:56:31 While the error codes and the bit flags are named
+ return reported_error(kBindingPatternProduction);
+ }
- const Error& assignment_pattern_error() const {
- return assignment_pattern_error_;
+ V8_INLINE const Error& assignment_pattern_error() const {
+ return reported_error(kAssignmentPatternProduction);
}
- const Error& arrow_formal_parameters_error() const {
- return arrow_formal_parameters_error_;
+ V8_INLINE const Error& arrow_formal_parameters_error() const {
+ return reported_error(kArrowFormalParametersProduction);
}
- const Error& duplicate_formal_parameter_error() const {
- return duplicate_formal_parameter_error_;
+ V8_INLINE const Error& duplicate_formal_parameter_error() const {
+ return reported_error(kDistinctFormalParametersProduction);
}
- const Error& strict_mode_formal_parameter_error() const {
- return strict_mode_formal_parameter_error_;
+ V8_INLINE const Error& strict_mode_formal_parameter_error() const {
+ return reported_error(kStrictModeFormalParametersProduction);
}
- const Error& strong_mode_formal_parameter_error() const {
- return strong_mode_formal_parameter_error_;
+ V8_INLINE const Error& strong_mode_formal_parameter_error() const {
+ return reported_error(kStrongModeFormalParametersProduction);
}
- const Error& let_pattern_error() const { return let_pattern_error_; }
+ V8_INLINE const Error& let_pattern_error() const {
+ return reported_error(kLetPatternProduction);
+ }
- bool has_cover_initialized_name() const {
+ V8_INLINE bool has_cover_initialized_name() const {
return !is_valid(CoverInitializedNameProduction);
}
- const Error& cover_initialized_name_error() const {
- return cover_initialized_name_error_;
+
+ V8_INLINE const Error& cover_initialized_name_error() const {
+ return reported_error(kCoverInitializedNameProduction);
}
- bool is_simple_parameter_list() const {
+ V8_INLINE bool is_simple_parameter_list() const {
return !(function_properties_ & NonSimpleParameter);
}
- void RecordNonSimpleParameter() {
+ V8_INLINE void RecordNonSimpleParameter() {
function_properties_ |= NonSimpleParameter;
}
@@ -168,9 +207,7 @@ class ExpressionClassifier {
const char* arg = nullptr) {
if (!is_valid_expression()) return;
invalid_productions_ |= ExpressionProduction;
- expression_error_.location = loc;
- expression_error_.message = message;
- expression_error_.arg = arg;
+ Add(Error(loc, message, kExpressionProduction, arg));
}
void RecordExpressionError(const Scanner::Location& loc,
@@ -178,10 +215,7 @@ class ExpressionClassifier {
ParseErrorType type, const char* arg = nullptr) {
if (!is_valid_expression()) return;
invalid_productions_ |= ExpressionProduction;
- expression_error_.location = loc;
- expression_error_.message = message;
- expression_error_.arg = arg;
- expression_error_.type = type;
+ Add(Error(loc, message, kExpressionProduction, arg, type));
}
void RecordFormalParameterInitializerError(const Scanner::Location& loc,
@@ -189,29 +223,43 @@ class ExpressionClassifier {
const char* arg = nullptr) {
if (!is_valid_formal_parameter_initializer()) return;
invalid_productions_ |= FormalParameterInitializerProduction;
- formal_parameter_initializer_error_.location = loc;
- formal_parameter_initializer_error_.message = message;
- formal_parameter_initializer_error_.arg = arg;
+ Add(Error(loc, message, kFormalParameterInitializerProduction, arg));
+ }
+
+ static Error BindingPatternError(const Scanner::Location& loc,
+ MessageTemplate::Template message,
+ const char* arg = nullptr) {
+ return Error(loc, message, kBindingPatternProduction, arg);
+ }
+
+ void RecordBindingPatternError(const Error& e) {
+ if (!is_valid_binding_pattern()) return;
+ invalid_productions_ |= BindingPatternProduction;
+ Add(e);
}
void RecordBindingPatternError(const Scanner::Location& loc,
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;
+ RecordBindingPatternError(BindingPatternError(loc, message, arg));
+ }
+
+ static Error AssignmentPatternError(const Scanner::Location& loc,
+ MessageTemplate::Template message,
+ const char* arg = nullptr) {
+ return Error(loc, message, kAssignmentPatternProduction, arg);
+ }
+
+ void RecordAssignmentPatternError(const Error& e) {
+ if (!is_valid_assignment_pattern()) return;
+ invalid_productions_ |= AssignmentPatternProduction;
+ Add(e);
}
void RecordAssignmentPatternError(const Scanner::Location& loc,
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;
+ RecordAssignmentPatternError(AssignmentPatternError(loc, message, arg));
}
void RecordPatternError(const Scanner::Location& loc,
@@ -226,17 +274,14 @@ class ExpressionClassifier {
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;
+ Add(Error(loc, message, kArrowFormalParametersProduction, arg));
}
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::kParamDupe;
- duplicate_formal_parameter_error_.arg = nullptr;
+ Add(Error(loc, MessageTemplate::kParamDupe,
+ kDistinctFormalParametersProduction));
}
// Record a binding that would be invalid in strict mode. Confusingly this
@@ -247,9 +292,7 @@ class ExpressionClassifier {
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;
+ Add(Error(loc, message, kStrictModeFormalParametersProduction, arg));
}
void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
@@ -257,9 +300,7 @@ class ExpressionClassifier {
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;
+ Add(Error(loc, message, kStrongModeFormalParametersProduction, arg));
}
void RecordLetPatternError(const Scanner::Location& loc,
@@ -267,9 +308,7 @@ class ExpressionClassifier {
const char* arg = nullptr) {
if (!is_valid_let_pattern()) return;
invalid_productions_ |= LetPatternProduction;
- let_pattern_error_.location = loc;
- let_pattern_error_.message = message;
- let_pattern_error_.arg = arg;
+ Add(Error(loc, message, kLetPatternProduction, arg));
}
void RecordCoverInitializedNameError(const Scanner::Location& loc,
@@ -277,79 +316,95 @@ class ExpressionClassifier {
const char* arg = nullptr) {
if (has_cover_initialized_name()) return;
invalid_productions_ |= CoverInitializedNameProduction;
- cover_initialized_name_error_.location = loc;
- cover_initialized_name_error_.message = message;
- cover_initialized_name_error_.arg = arg;
+ Add(Error(loc, message, kCoverInitializedNameProduction, arg));
}
void ForgiveCoverInitializedNameError() {
+ if (!(invalid_productions_ & CoverInitializedNameProduction)) return;
invalid_productions_ &= ~CoverInitializedNameProduction;
- cover_initialized_name_error_ = Error();
+ Error& e = reported_error(kCoverInitializedNameProduction);
+ e.kind = kUnusedError;
}
void ForgiveAssignmentPatternError() {
+ if (!(invalid_productions_ & AssignmentPatternProduction)) return;
invalid_productions_ &= ~AssignmentPatternProduction;
- assignment_pattern_error_ = Error();
+ Error& e = reported_error(kAssignmentPatternProduction);
+ e.kind = kUnusedError;
}
void Accumulate(ExpressionClassifier* inner,
unsigned productions = StandardProductions,
bool merge_non_patterns = true) {
+ DCHECK_EQ(inner->reported_errors_, reported_errors_);
+ DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_);
+ DCHECK_EQ(inner->reported_errors_end_, reported_errors_->length());
if (merge_non_patterns) MergeNonPatterns(inner);
// 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 & FormalParameterInitializerProduction)
- formal_parameter_initializer_error_ =
- inner->formal_parameter_initializer_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 (errors & StrictModeFormalParametersProduction)
- strict_mode_formal_parameter_error_ =
- inner->strict_mode_formal_parameter_error_;
- if (errors & StrongModeFormalParametersProduction)
- strong_mode_formal_parameter_error_ =
- inner->strong_mode_formal_parameter_error_;
- if (errors & LetPatternProduction)
- let_pattern_error_ = inner->let_pattern_error_;
- if (errors & CoverInitializedNameProduction)
- cover_initialized_name_error_ = inner->cover_initialized_name_error_;
- }
+ int next = inner->reported_errors_begin_;
+ if (non_arrow_inner_invalid_productions) {
+ unsigned non_arrow_productions =
+ productions & ~ArrowFormalParametersProduction;
+ unsigned errors =
+ non_arrow_productions & non_arrow_inner_invalid_productions;
+ errors &= ~invalid_productions_;
+
+ // 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()) {
+ // Also copy function properties if expecting an arrow function
+ // parameter.
+ function_properties_ |= inner->function_properties_;
+
+ if (!inner->is_valid_binding_pattern())
+ errors |= ArrowFormalParametersProduction;
+ }
- // 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()) {
- // Also copy function properties if expecting an arrow function
- // parameter.
- function_properties_ |= inner->function_properties_;
-
- if (!inner->is_valid_binding_pattern()) {
- invalid_productions_ |= ArrowFormalParametersProduction;
- arrow_formal_parameters_error_ = inner->binding_pattern_error_;
+ if (errors != 0) {
+ invalid_productions_ |= errors;
+ int arrow_index = inner->reported_errors_end_;
+ for (int i = inner->reported_errors_begin_;
+ i < inner->reported_errors_end_; i++) {
+ if (reported_errors_->at(i).kind == kUnusedError ||
+ reported_errors_->at(i).kind == kArrowFormalParametersProduction)
+ continue;
+ if (errors & (1 << reported_errors_->at(i).kind))
+ Move(next++, i);
+ if (reported_errors_->at(i).kind == kBindingPatternProduction &&
+ errors & ArrowFormalParametersProduction) {
+ if (next <= i) {
+ Move(next, i);
+ reported_errors_->at(next++).kind =
+ kArrowFormalParametersProduction;
+ } else {
+ DCHECK_EQ(next, i+1);
+ arrow_index = i;
+ }
+ }
+ }
+ if (arrow_index < inner->reported_errors_end_) {
+ Add(reported_errors_->at(arrow_index));
+ reported_errors_->at(next++).kind = kArrowFormalParametersProduction;
+ }
}
}
+ DCHECK_EQ(reported_errors_end_, next);
+ reported_errors_->Rewind(next);
+ inner->reported_errors_begin_ = inner->reported_errors_end_ = next;
}
V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
V8_INLINE void Discard() {
+ if (reported_errors_end_ == reported_errors_->length()) {
+ reported_errors_->Rewind(reported_errors_begin_);
+ reported_errors_end_ = reported_errors_begin_;
+ }
+ DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
}
@@ -360,25 +415,49 @@ class ExpressionClassifier {
}
private:
+ V8_INLINE Error& reported_error(ErrorKind kind) const {
+ if (invalid_productions_ & (1 << kind)) {
+ for (int i = reported_errors_begin_; i < reported_errors_end_; i++) {
+ if (reported_errors_->at(i).kind == kind)
+ return reported_errors_->at(i);
+ }
+ }
+ // We should only be looking for an error when we know that one has
+ // been reported. But we're not... So this is to make sure we have
+ // the same behaviour.
+ static Error none;
+ return none;
+ }
+
+ V8_INLINE void Add(const Error& e) {
+ DCHECK_EQ(reported_errors_end_, reported_errors_->length());
+ reported_errors_->Add(e, zone_);
caitp (gmail) 2016/02/18 16:57:47 It might be worth having the very commonly used on
nickie 2016/02/19 08:56:31 If you could suggest a subset, I could try to benc
caitp (gmail) 2016/02/19 09:07:28 the main one is Object/Array Literals vs Assignmen
nickie 2016/02/19 09:25:50 One way to go then is to always store BindingPatte
+ reported_errors_end_++;
+ }
+
+ V8_INLINE void Move(int next, int i) {
+ DCHECK_EQ(reported_errors_end_, next);
+ DCHECK_LE(next, i);
+ DCHECK_LT(i, reported_errors_->length());
+ if (next < i) reported_errors_->at(next++) = reported_errors_->at(i);
+ reported_errors_end_++;
+ }
+
Zone* zone_;
ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_;
int non_pattern_begin_;
- unsigned invalid_productions_;
- unsigned function_properties_;
- Error expression_error_;
- Error formal_parameter_initializer_error_;
- Error binding_pattern_error_;
- Error assignment_pattern_error_;
- Error arrow_formal_parameters_error_;
- Error duplicate_formal_parameter_error_;
- Error strict_mode_formal_parameter_error_;
- Error strong_mode_formal_parameter_error_;
- Error let_pattern_error_;
- Error cover_initialized_name_error_;
+ unsigned invalid_productions_ : 14;
+ unsigned function_properties_ : 2;
+ ZoneList<Error>* reported_errors_;
+ int reported_errors_begin_;
+ int reported_errors_end_;
DuplicateFinder* duplicate_finder_;
};
+#undef ERROR_CODES
+
+
} // namespace internal
} // namespace v8
« no previous file with comments | « no previous file | src/parsing/parser.h » ('j') | src/parsing/parser-base.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698