Commit 87494a80 authored by wingo@igalia.com's avatar wingo@igalia.com

Rewind additional parser state when reinterpreting arrow arguments

The new ParserCheckpoint mechanism resets some state, notably the
bailout ID counter but also some statement counters (only applicable
once we get "do" expressions) when we decide to reinterpret a comma
expression as arrow function arguments.

R=marja@chromium.org, rossberg@chromium.org
BUG=v8:3475
LOG=N

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22906 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b47fe573
...@@ -339,6 +339,23 @@ class RegExpParser BASE_EMBEDDED { ...@@ -339,6 +339,23 @@ class RegExpParser BASE_EMBEDDED {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// JAVASCRIPT PARSING // JAVASCRIPT PARSING
class ParserCheckpoint BASE_EMBEDDED {
public:
template <typename Parser>
explicit ParserCheckpoint(Parser* parser) {
isolate_ = parser->zone()->isolate();
saved_ast_node_id_ = isolate_->ast_node_id();
}
void Restore() { isolate_->set_ast_node_id(saved_ast_node_id_); }
private:
Isolate* isolate_;
int saved_ast_node_id_;
};
class Parser; class Parser;
class SingletonLogger; class SingletonLogger;
...@@ -354,6 +371,7 @@ class ParserTraits { ...@@ -354,6 +371,7 @@ class ParserTraits {
typedef v8::internal::Scope* ScopePtr; typedef v8::internal::Scope* ScopePtr;
typedef Variable GeneratorVariable; typedef Variable GeneratorVariable;
typedef v8::internal::Zone Zone; typedef v8::internal::Zone Zone;
typedef ParserCheckpoint Checkpoint;
typedef v8::internal::AstProperties AstProperties; typedef v8::internal::AstProperties AstProperties;
typedef Vector<VariableProxy*> ParameterIdentifierVector; typedef Vector<VariableProxy*> ParameterIdentifierVector;
......
...@@ -114,6 +114,8 @@ class ParserBase : public Traits { ...@@ -114,6 +114,8 @@ class ParserBase : public Traits {
} }
protected: protected:
friend class Traits::Type::Checkpoint;
enum AllowEvalOrArgumentsAsIdentifier { enum AllowEvalOrArgumentsAsIdentifier {
kAllowEvalOrArguments, kAllowEvalOrArguments,
kDontAllowEvalOrArguments kDontAllowEvalOrArguments
...@@ -124,6 +126,8 @@ class ParserBase : public Traits { ...@@ -124,6 +126,8 @@ class ParserBase : public Traits {
PARSE_EAGERLY PARSE_EAGERLY
}; };
class ParserCheckpoint;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// FunctionState and BlockState together implement the parser's scope stack. // FunctionState and BlockState together implement the parser's scope stack.
// The parser's current scope is in scope_. BlockState and FunctionState // The parser's current scope is in scope_. BlockState and FunctionState
...@@ -219,6 +223,38 @@ class ParserBase : public Traits { ...@@ -219,6 +223,38 @@ class ParserBase : public Traits {
typename Traits::Type::Factory factory_; typename Traits::Type::Factory factory_;
friend class ParserTraits; friend class ParserTraits;
friend class ParserCheckpoint;
};
// Annoyingly, arrow functions first parse as comma expressions, then when we
// see the => we have to go back and reinterpret the arguments as being formal
// parameters. To do so we need to reset some of the parser state back to
// what it was before the arguments were first seen.
class ParserCheckpoint : public Traits::Type::Checkpoint {
public:
template <typename Parser>
explicit ParserCheckpoint(Parser* parser)
: Traits::Type::Checkpoint(parser) {
function_state_ = parser->function_state_;
next_materialized_literal_index_ =
function_state_->next_materialized_literal_index_;
next_handler_index_ = function_state_->next_handler_index_;
expected_property_count_ = function_state_->expected_property_count_;
}
void Restore() {
Traits::Type::Checkpoint::Restore();
function_state_->next_materialized_literal_index_ =
next_materialized_literal_index_;
function_state_->next_handler_index_ = next_handler_index_;
function_state_->expected_property_count_ = expected_property_count_;
}
private:
FunctionState* function_state_;
int next_materialized_literal_index_;
int next_handler_index_;
int expected_property_count_;
}; };
class ParsingModeScope BASE_EMBEDDED { class ParsingModeScope BASE_EMBEDDED {
...@@ -1021,6 +1057,14 @@ class PreParserFactory { ...@@ -1021,6 +1057,14 @@ class PreParserFactory {
}; };
class PreParserCheckpoint BASE_EMBEDDED {
public:
template <typename Parser>
explicit PreParserCheckpoint(Parser* parser) {}
void Restore() {}
};
class PreParser; class PreParser;
class PreParserTraits { class PreParserTraits {
...@@ -1033,6 +1077,7 @@ class PreParserTraits { ...@@ -1033,6 +1077,7 @@ class PreParserTraits {
// Used by FunctionState and BlockState. // Used by FunctionState and BlockState.
typedef PreParserScope Scope; typedef PreParserScope Scope;
typedef PreParserScope ScopePtr; typedef PreParserScope ScopePtr;
typedef PreParserCheckpoint Checkpoint;
// PreParser doesn't need to store generator variables. // PreParser doesn't need to store generator variables.
typedef void GeneratorVariable; typedef void GeneratorVariable;
...@@ -2006,10 +2051,12 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { ...@@ -2006,10 +2051,12 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
} }
if (fni_ != NULL) fni_->Enter(); if (fni_ != NULL) fni_->Enter();
ParserCheckpoint checkpoint(this);
ExpressionT expression = ExpressionT expression =
this->ParseConditionalExpression(accept_IN, CHECK_OK); this->ParseConditionalExpression(accept_IN, CHECK_OK);
if (allow_arrow_functions() && peek() == Token::ARROW) { if (allow_arrow_functions() && peek() == Token::ARROW) {
checkpoint.Restore();
expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos, expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
expression, CHECK_OK); expression, CHECK_OK);
return expression; return expression;
......
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