Reviewers: rossberg,

Message:
Perhaps there is a way to do this in a less nasty fashion, dunno.  Hold your
nose and PTAL :)

Description:
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.

[email protected]
BUG=v8:3475
LOG=N

Please review this at https://codereview.chromium.org/437393004/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+73, -0 lines):
  M src/parser.h
  M src/preparser.h


Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index 2d5ce2f3760bc929fa04eb967c54ef39db691e63..89f40db8d60fbab2257c0283f11c0d54fc58162e 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -339,6 +339,28 @@ class RegExpParser BASE_EMBEDDED {
// ----------------------------------------------------------------------------
 // JAVASCRIPT PARSING

+
+class ParserCheckpoint BASE_EMBEDDED {
+ public:
+  ParserCheckpoint() : isolate_(NULL) {}
+
+  template <typename Parser>
+  void Save(Parser* parser) {
+    DCHECK(!isolate_);
+    isolate_ = parser->zone()->isolate();
+    saved_ast_node_id_ = isolate_->ast_node_id();
+  }
+  void Restore() {
+    DCHECK(isolate_);
+    isolate_->set_ast_node_id(saved_ast_node_id_);
+  }
+
+ private:
+  Isolate* isolate_;
+  int saved_ast_node_id_;
+};
+
+
 class Parser;
 class SingletonLogger;

@@ -354,6 +376,7 @@ class ParserTraits {
     typedef v8::internal::Scope* ScopePtr;
     typedef Variable GeneratorVariable;
     typedef v8::internal::Zone Zone;
+    typedef ParserCheckpoint Checkpoint;

     typedef v8::internal::AstProperties AstProperties;
     typedef Vector<VariableProxy*> ParameterIdentifierVector;
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index ff6bd2728c929e865e90d137cf9040177b8b5e9f..183fb91e84d85ea6ee3e059bc4258461193d9a9d 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -114,6 +114,8 @@ class ParserBase : public Traits {
   }

  protected:
+  friend class Traits::Type::Checkpoint;
+
   enum AllowEvalOrArgumentsAsIdentifier {
     kAllowEvalOrArguments,
     kDontAllowEvalOrArguments
@@ -124,6 +126,8 @@ class ParserBase : public Traits {
     PARSE_EAGERLY
   };

+  class ParserCheckpoint;
+
// --------------------------------------------------------------------------- // FunctionState and BlockState together implement the parser's scope stack.
   // The parser's current scope is in scope_. BlockState and FunctionState
@@ -219,6 +223,39 @@ class ParserBase : public Traits {
     typename Traits::Type::Factory factory_;

     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:
+    ParserCheckpoint() : Traits::Type::Checkpoint() {}
+
+    void Save(ParserBase* parser) {
+      Traits::Type::Checkpoint::Save(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 {
@@ -1021,6 +1058,15 @@ class PreParserFactory {
 };


+class PreParserCheckpoint BASE_EMBEDDED {
+ public:
+  PreParserCheckpoint() {}
+  template <typename Parser>
+  void Save(Parser* parser) {}
+  void Restore() {}
+};
+
+
 class PreParser;

 class PreParserTraits {
@@ -1033,6 +1079,7 @@ class PreParserTraits {
     // Used by FunctionState and BlockState.
     typedef PreParserScope Scope;
     typedef PreParserScope ScopePtr;
+    typedef PreParserCheckpoint Checkpoint;

     // PreParser doesn't need to store generator variables.
     typedef void GeneratorVariable;
@@ -2001,10 +2048,13 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
   }

   if (fni_ != NULL) fni_->Enter();
+  ParserCheckpoint checkpoint;
+  checkpoint.Save(this);
   ExpressionT expression =
       this->ParseConditionalExpression(accept_IN, CHECK_OK);

   if (allow_arrow_functions() && peek() == Token::ARROW) {
+    checkpoint.Restore();
     expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
                                                  expression, CHECK_OK);
     return expression;


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to