Commit dfb8d333 authored by nikolaos's avatar nikolaos Committed by Commit bot

Reduce the memory footprint of expression classifiers

This patch attempts to reduce the (stack) memory footprint of
expression classifiers.  Instead of keeping space in each
classifier for all possible error messages that will
(potentially) be reported, if an expression turns out to be
a pattern or a non-pattern, such error messages are placed in
a list shared by the FunctionState and each classifier keeps a
couple of indices in this list.  This requires that classifiers
are used strictly in a stack-based fashion, which is also in line
with my previous patch for revisiting non-pattern rewriting.

R=adamk@chromium.org
BUG=chromium:528697

Review-Url: https://codereview.chromium.org/1708193003
Cr-Commit-Position: refs/heads/master@{#36897}
parent 6e700b7f
......@@ -440,6 +440,8 @@ class CallSite {
"Too many arguments in function call (only 65535 allowed)") \
T(TooManyParameters, \
"Too many parameters in function definition (only 65535 allowed)") \
T(TooManySpreads, \
"Literal containing too many nested spreads (up to 65534 allowed)") \
T(TooManyVariables, "Too many variables declared (only 4194303 allowed)") \
T(TypedArrayTooShort, \
"Derived TypedArray constructor created an array which was too small") \
......
This diff is collapsed.
......@@ -387,8 +387,8 @@ class ParserBase : public Traits {
typename Traits::Type::Factory* factory() { return factory_; }
const List<DestructuringAssignment>& destructuring_assignments_to_rewrite()
const {
const ZoneList<DestructuringAssignment>&
destructuring_assignments_to_rewrite() const {
return destructuring_assignments_to_rewrite_;
}
......@@ -410,6 +410,10 @@ class ParserBase : public Traits {
}
}
ZoneList<typename ExpressionClassifier::Error>* GetReportedErrorList() {
return &reported_errors_;
}
ReturnExprContext return_expr_context() const {
return return_expr_context_;
}
......@@ -431,13 +435,16 @@ class ParserBase : public Traits {
private:
void AddDestructuringAssignment(DestructuringAssignment pair) {
destructuring_assignments_to_rewrite_.Add(pair);
destructuring_assignments_to_rewrite_.Add(pair, (*scope_stack_)->zone());
}
V8_INLINE Scope* scope() { return *scope_stack_; }
void AddNonPatternForRewriting(ExpressionT expr) {
void AddNonPatternForRewriting(ExpressionT expr, bool* ok) {
non_patterns_to_rewrite_.Add(expr, (*scope_stack_)->zone());
if (non_patterns_to_rewrite_.length() >=
std::numeric_limits<uint16_t>::max())
*ok = false;
}
// Used to assign an index to each literal that needs materialization in
......@@ -468,11 +475,13 @@ class ParserBase : public Traits {
Scope** scope_stack_;
Scope* outer_scope_;
List<DestructuringAssignment> destructuring_assignments_to_rewrite_;
ZoneList<DestructuringAssignment> destructuring_assignments_to_rewrite_;
TailCallExpressionList tail_call_expressions_;
ReturnExprContext return_expr_context_;
ZoneList<ExpressionT> non_patterns_to_rewrite_;
ZoneList<typename ExpressionClassifier::Error> reported_errors_;
typename Traits::Type::Factory* factory_;
// If true, the next (and immediately following) function literal is
......@@ -1196,9 +1205,11 @@ ParserBase<Traits>::FunctionState::FunctionState(
outer_function_state_(*function_state_stack),
scope_stack_(scope_stack),
outer_scope_(*scope_stack),
destructuring_assignments_to_rewrite_(16, scope->zone()),
tail_call_expressions_(scope->zone()),
return_expr_context_(ReturnExprContext::kInsideValidBlock),
non_patterns_to_rewrite_(0, scope->zone()),
reported_errors_(16, scope->zone()),
factory_(factory),
next_function_is_parenthesized_(false),
this_function_is_parenthesized_(false) {
......@@ -1555,12 +1566,11 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
// Parentheses are not valid on the LHS of a BindingPattern, so we use the
// is_valid_binding_pattern() check to detect multiple levels of
// parenthesization.
if (!classifier->is_valid_binding_pattern()) {
ArrowFormalParametersUnexpectedToken(classifier);
}
bool pattern_error = !classifier->is_valid_binding_pattern();
classifier->RecordPatternError(scanner()->peek_location(),
MessageTemplate::kUnexpectedToken,
Token::String(Token::LPAREN));
if (pattern_error) ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::LPAREN);
if (Check(Token::RPAREN)) {
// ()=>x. The continuation that looks for the => is in
......@@ -1693,6 +1703,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
seen_rest = is_rest = true;
}
int pos = position(), expr_pos = peek_position();
ExpressionClassifier binding_classifier(this);
ExpressionT right = this->ParseAssignmentExpression(
accept_IN, &binding_classifier, CHECK_OK);
classifier->Accumulate(&binding_classifier,
......@@ -1780,7 +1791,15 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
literal_index, pos);
if (first_spread_index >= 0) {
result = factory()->NewRewritableExpression(result);
Traits::QueueNonPatternForRewriting(result);
Traits::QueueNonPatternForRewriting(result, ok);
if (!*ok) {
// If the non-pattern rewriting mechanism is used in the future for
// rewriting other things than spreads, this error message will have
// to change. Also, this error message will never appear while pre-
// parsing (this is OK, as it is an implementation limitation).
ReportMessage(MessageTemplate::kTooManySpreads);
return this->EmptyExpression();
}
}
return result;
}
......@@ -2227,9 +2246,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
}
if (peek() == Token::ARROW) {
classifier->RecordPatternError(scanner()->peek_location(),
MessageTemplate::kUnexpectedToken,
Token::String(Token::ARROW));
Scanner::Location arrow_loc = scanner()->peek_location();
ValidateArrowFormalParameters(&arrow_formals_classifier, expression,
parenthesized_formals, is_async, CHECK_OK);
// This reads strangely, but is correct: it checks whether any
......@@ -2266,6 +2283,10 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
}
expression = this->ParseArrowFunctionLiteral(
accept_IN, parameters, is_async, arrow_formals_classifier, CHECK_OK);
arrow_formals_classifier.Discard();
classifier->RecordPatternError(arrow_loc,
MessageTemplate::kUnexpectedToken,
Token::String(Token::ARROW));
if (fni_ != nullptr) fni_->Infer();
......@@ -2505,8 +2526,8 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN,
if (peek() != Token::CONDITIONAL) return expression;
CheckNoTailCallExpressions(classifier, CHECK_OK);
Traits::RewriteNonPattern(classifier, CHECK_OK);
ArrowFormalParametersUnexpectedToken(classifier);
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::CONDITIONAL);
// In parsing the first assignment expression in conditional
// expressions we always accept the 'in' keyword; see ECMA-262,
......
......@@ -2539,7 +2539,6 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
ReportUnexpectedToken(Next());
*ok = false;
return nullptr;
default:
break;
}
......@@ -5649,13 +5648,19 @@ Expression* ParserTraits::RewriteAwaitExpression(Expression* value,
return factory->NewYield(generator_object, do_expr, nopos);
}
Zone* ParserTraits::zone() const {
return parser_->function_state_->scope()->zone();
ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
return parser_->function_state_->non_patterns_to_rewrite();
}
ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
return parser_->function_state_->non_patterns_to_rewrite();
ZoneList<typename ParserTraits::Type::ExpressionClassifier::Error>*
ParserTraits::GetReportedErrorList() const {
return parser_->function_state_->GetReportedErrorList();
}
Zone* ParserTraits::zone() const {
return parser_->function_state_->scope()->zone();
}
......@@ -5872,9 +5877,9 @@ void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
}
void ParserTraits::QueueNonPatternForRewriting(Expression* expr) {
void ParserTraits::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
DCHECK(expr->IsRewritableExpression());
parser_->function_state_->AddNonPatternForRewriting(expr);
parser_->function_state_->AddNonPatternForRewriting(expr, ok);
}
......
......@@ -658,7 +658,7 @@ class ParserTraits {
V8_INLINE void QueueDestructuringAssignmentForRewriting(
Expression* assignment);
V8_INLINE void QueueNonPatternForRewriting(Expression* expr);
V8_INLINE void QueueNonPatternForRewriting(Expression* expr, bool* ok);
void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
const AstRawString* name);
......@@ -670,6 +670,8 @@ class ParserTraits {
V8_INLINE void RewriteNonPattern(Type::ExpressionClassifier* classifier,
bool* ok);
V8_INLINE ZoneList<typename Type::ExpressionClassifier::Error>*
GetReportedErrorList() const;
V8_INLINE Zone* zone() const;
V8_INLINE ZoneList<Expression*>* GetNonPatternList() const;
......
......@@ -974,7 +974,7 @@ class PreParserTraits {
}
inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {}
inline void QueueNonPatternForRewriting(PreParserExpression) {}
inline void QueueNonPatternForRewriting(PreParserExpression, bool* ok) {}
void SetFunctionNameFromPropertyName(PreParserExpression,
PreParserIdentifier) {}
......@@ -987,6 +987,8 @@ class PreParserTraits {
inline PreParserExpression RewriteAwaitExpression(PreParserExpression value,
int pos);
V8_INLINE ZoneList<typename Type::ExpressionClassifier::Error>*
GetReportedErrorList() const;
V8_INLINE Zone* zone() const;
V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const;
......@@ -1214,13 +1216,19 @@ PreParserExpression PreParserTraits::RewriteAwaitExpression(
return value;
}
Zone* PreParserTraits::zone() const {
return pre_parser_->function_state_->scope()->zone();
ZoneList<PreParserExpression>* PreParserTraits::GetNonPatternList() const {
return pre_parser_->function_state_->non_patterns_to_rewrite();
}
ZoneList<PreParserExpression>* PreParserTraits::GetNonPatternList() const {
return pre_parser_->function_state_->non_patterns_to_rewrite();
ZoneList<typename PreParserTraits::Type::ExpressionClassifier::Error>*
PreParserTraits::GetReportedErrorList() const {
return pre_parser_->function_state_->GetReportedErrorList();
}
Zone* PreParserTraits::zone() const {
return pre_parser_->function_state_->scope()->zone();
}
......
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