| Index: src/parser.cc
 | 
| diff --git a/src/parser.cc b/src/parser.cc
 | 
| index 40e8071b9161b5ba8cd247d15a4979449767a2b4..80abc63b4b204a7e687fb6748498f049bcc067fb 100644
 | 
| --- a/src/parser.cc
 | 
| +++ b/src/parser.cc
 | 
| @@ -459,44 +459,39 @@ class TargetScope BASE_EMBEDDED {
 | 
|  
 | 
|  
 | 
|  // ----------------------------------------------------------------------------
 | 
| -// LexicalScope and SaveScope are stack allocated support classes to facilitate
 | 
| -// anipulation of the Parser's scope stack. The constructor sets the parser's
 | 
| -// top scope to the incoming scope, and the destructor resets it. Additionally,
 | 
| -// LexicalScope stores transient information used during parsing.
 | 
| +// FunctionState and BlockState together implement the parser's scope stack.
 | 
| +// The parser's current scope is in top_scope_.  The BlockState and
 | 
| +// FunctionState constructors push on the scope stack and the destructors
 | 
| +// pop.  They are also used to hold the parser's per-function and per-block
 | 
| +// state.
 | 
|  
 | 
| -
 | 
| -class SaveScope BASE_EMBEDDED {
 | 
| +class Parser::BlockState BASE_EMBEDDED {
 | 
|   public:
 | 
| -  SaveScope(Parser* parser, Scope* scope)
 | 
| +  BlockState(Parser* parser, Scope* scope)
 | 
|        : parser_(parser),
 | 
| -        previous_top_scope_(parser->top_scope_) {
 | 
| +        outer_scope_(parser->top_scope_) {
 | 
|      parser->top_scope_ = scope;
 | 
|    }
 | 
|  
 | 
| -  ~SaveScope() {
 | 
| -    parser_->top_scope_ = previous_top_scope_;
 | 
| -  }
 | 
| +  ~BlockState() { parser_->top_scope_ = outer_scope_; }
 | 
|  
 | 
|   private:
 | 
| -  // Bookkeeping
 | 
|    Parser* parser_;
 | 
| -  // Previous values
 | 
| -  Scope* previous_top_scope_;
 | 
| +  Scope* outer_scope_;
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class LexicalScope BASE_EMBEDDED {
 | 
| +class Parser::FunctionState BASE_EMBEDDED {
 | 
|   public:
 | 
| -  LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
 | 
| -  ~LexicalScope();
 | 
| +  FunctionState(Parser* parser, Scope* scope, Isolate* isolate);
 | 
| +  ~FunctionState();
 | 
|  
 | 
|    int NextMaterializedLiteralIndex() {
 | 
| -    int next_index =
 | 
| -        materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
 | 
| -    materialized_literal_count_++;
 | 
| -    return next_index;
 | 
| +    return next_materialized_literal_index_++;
 | 
| +  }
 | 
| +  int materialized_literal_count() {
 | 
| +    return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
 | 
|    }
 | 
| -  int materialized_literal_count() { return materialized_literal_count_; }
 | 
|  
 | 
|    void SetThisPropertyAssignmentInfo(
 | 
|        bool only_simple_this_property_assignments,
 | 
| @@ -516,10 +511,10 @@ class LexicalScope BASE_EMBEDDED {
 | 
|    int expected_property_count() { return expected_property_count_; }
 | 
|  
 | 
|   private:
 | 
| -  // Captures the number of literals that need materialization in the
 | 
| -  // function.  Includes regexp literals, and boilerplate for object
 | 
| -  // and array literals.
 | 
| -  int materialized_literal_count_;
 | 
| +  // Used to assign an index to each literal that needs materialization in
 | 
| +  // the function.  Includes regexp literals, and boilerplate for object and
 | 
| +  // array literals.
 | 
| +  int next_materialized_literal_index_;
 | 
|  
 | 
|    // Properties count estimation.
 | 
|    int expected_property_count_;
 | 
| @@ -529,34 +524,34 @@ class LexicalScope BASE_EMBEDDED {
 | 
|    bool only_simple_this_property_assignments_;
 | 
|    Handle<FixedArray> this_property_assignments_;
 | 
|  
 | 
| -  // Bookkeeping
 | 
|    Parser* parser_;
 | 
| -  // Previous values
 | 
| -  LexicalScope* lexical_scope_parent_;
 | 
| -  Scope* previous_scope_;
 | 
| -  unsigned previous_ast_node_id_;
 | 
| +  FunctionState* outer_function_state_;
 | 
| +  Scope* outer_scope_;
 | 
| +  unsigned saved_ast_node_id_;
 | 
|  };
 | 
|  
 | 
|  
 | 
| -LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
 | 
| -  : materialized_literal_count_(0),
 | 
| -    expected_property_count_(0),
 | 
| -    only_simple_this_property_assignments_(false),
 | 
| -    this_property_assignments_(isolate->factory()->empty_fixed_array()),
 | 
| -    parser_(parser),
 | 
| -    lexical_scope_parent_(parser->lexical_scope_),
 | 
| -    previous_scope_(parser->top_scope_),
 | 
| -    previous_ast_node_id_(isolate->ast_node_id()) {
 | 
| +Parser::FunctionState::FunctionState(Parser* parser,
 | 
| +                                     Scope* scope,
 | 
| +                                     Isolate* isolate)
 | 
| +    : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
 | 
| +      expected_property_count_(0),
 | 
| +      only_simple_this_property_assignments_(false),
 | 
| +      this_property_assignments_(isolate->factory()->empty_fixed_array()),
 | 
| +      parser_(parser),
 | 
| +      outer_function_state_(parser->current_function_state_),
 | 
| +      outer_scope_(parser->top_scope_),
 | 
| +      saved_ast_node_id_(isolate->ast_node_id()) {
 | 
|    parser->top_scope_ = scope;
 | 
| -  parser->lexical_scope_ = this;
 | 
| +  parser->current_function_state_ = this;
 | 
|    isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -LexicalScope::~LexicalScope() {
 | 
| -  parser_->top_scope_ = previous_scope_;
 | 
| -  parser_->lexical_scope_ = lexical_scope_parent_;
 | 
| -  parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
 | 
| +Parser::FunctionState::~FunctionState() {
 | 
| +  parser_->top_scope_ = outer_scope_;
 | 
| +  parser_->current_function_state_ = outer_function_state_;
 | 
| +  parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -592,7 +587,7 @@ Parser::Parser(Handle<Script> script,
 | 
|        script_(script),
 | 
|        scanner_(isolate_->unicode_cache()),
 | 
|        top_scope_(NULL),
 | 
| -      lexical_scope_(NULL),
 | 
| +      current_function_state_(NULL),
 | 
|        target_stack_(NULL),
 | 
|        allow_natives_syntax_(allow_natives_syntax),
 | 
|        extension_(extension),
 | 
| @@ -651,7 +646,7 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
 | 
|    { Scope* scope = NewScope(top_scope_, type);
 | 
|      scope->set_start_position(0);
 | 
|      scope->set_end_position(source->length());
 | 
| -    LexicalScope lexical_scope(this, scope, isolate());
 | 
| +    FunctionState function_state(this, scope, isolate());
 | 
|      ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode);
 | 
|      top_scope_->SetStrictModeFlag(strict_mode);
 | 
|      ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
 | 
| @@ -672,10 +667,10 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
 | 
|            no_name,
 | 
|            top_scope_,
 | 
|            body,
 | 
| -          lexical_scope.materialized_literal_count(),
 | 
| -          lexical_scope.expected_property_count(),
 | 
| -          lexical_scope.only_simple_this_property_assignments(),
 | 
| -          lexical_scope.this_property_assignments(),
 | 
| +          function_state.materialized_literal_count(),
 | 
| +          function_state.expected_property_count(),
 | 
| +          function_state.only_simple_this_property_assignments(),
 | 
| +          function_state.this_property_assignments(),
 | 
|            0,
 | 
|            FunctionLiteral::ANONYMOUS_EXPRESSION,
 | 
|            false);  // Does not have duplicate parameters.
 | 
| @@ -742,7 +737,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
 | 
|      if (!info->closure().is_null()) {
 | 
|        scope = Scope::DeserializeScopeChain(info, scope);
 | 
|      }
 | 
| -    LexicalScope lexical_scope(this, scope, isolate());
 | 
| +    FunctionState function_state(this, scope, isolate());
 | 
|      ASSERT(scope->strict_mode_flag() == kNonStrictMode ||
 | 
|             scope->strict_mode_flag() == info->strict_mode_flag());
 | 
|      ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag());
 | 
| @@ -1217,7 +1212,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
 | 
|          this_property_assignment_finder.only_simple_this_property_assignments()
 | 
|          && top_scope_->declarations()->length() == 0;
 | 
|      if (only_simple_this_property_assignments) {
 | 
| -      lexical_scope_->SetThisPropertyAssignmentInfo(
 | 
| +      current_function_state_->SetThisPropertyAssignmentInfo(
 | 
|            only_simple_this_property_assignments,
 | 
|            this_property_assignment_finder.GetThisPropertyAssignments());
 | 
|      }
 | 
| @@ -1609,7 +1604,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
 | 
|    // Parse the statements and collect escaping labels.
 | 
|    Expect(Token::LBRACE, CHECK_OK);
 | 
|    block_scope->set_start_position(scanner().location().beg_pos);
 | 
| -  { SaveScope save_scope(this, block_scope);
 | 
| +  { BlockState block_state(this, block_scope);
 | 
|      TargetCollector collector;
 | 
|      Target target(&this->target_stack_, &collector);
 | 
|      Target target_body(&this->target_stack_, body);
 | 
| @@ -2151,7 +2146,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
 | 
|    top_scope_->DeclarationScope()->RecordWithStatement();
 | 
|    Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
 | 
|    Statement* stmt;
 | 
| -  { SaveScope save_scope(this, with_scope);
 | 
| +  { BlockState block_state(this, with_scope);
 | 
|      with_scope->set_start_position(scanner().peek_location().beg_pos);
 | 
|      stmt = ParseStatement(labels, CHECK_OK);
 | 
|      with_scope->set_end_position(scanner().location().end_pos);
 | 
| @@ -2298,7 +2293,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
 | 
|        catch_variable =
 | 
|            catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
 | 
|  
 | 
| -      SaveScope save_scope(this, catch_scope);
 | 
| +      BlockState block_state(this, catch_scope);
 | 
|        catch_block = ParseBlock(NULL, CHECK_OK);
 | 
|      } else {
 | 
|        Expect(Token::LBRACE, CHECK_OK);
 | 
| @@ -2649,13 +2644,13 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
 | 
|        property != NULL &&
 | 
|        property->obj()->AsVariableProxy() != NULL &&
 | 
|        property->obj()->AsVariableProxy()->is_this()) {
 | 
| -    lexical_scope_->AddProperty();
 | 
| +    current_function_state_->AddProperty();
 | 
|    }
 | 
|  
 | 
|    // If we assign a function literal to a property we pretenure the
 | 
|    // literal so it can be added as a constant function property.
 | 
|    if (property != NULL && right->AsFunctionLiteral() != NULL) {
 | 
| -    right->AsFunctionLiteral()->set_pretenure(true);
 | 
| +    right->AsFunctionLiteral()->set_pretenure();
 | 
|    }
 | 
|  
 | 
|    if (fni_ != NULL) {
 | 
| @@ -3309,7 +3304,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
 | 
|    Expect(Token::RBRACK, CHECK_OK);
 | 
|  
 | 
|    // Update the scope information before the pre-parsing bailout.
 | 
| -  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 | 
| +  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
 | 
|  
 | 
|    // Allocate a fixed array to hold all the object literals.
 | 
|    Handle<FixedArray> object_literals =
 | 
| @@ -3789,7 +3784,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
 | 
|      // literal so it can be added as a constant function property.
 | 
|      if (value->AsFunctionLiteral() != NULL) {
 | 
|        has_function = true;
 | 
| -      value->AsFunctionLiteral()->set_pretenure(true);
 | 
| +      value->AsFunctionLiteral()->set_pretenure();
 | 
|      }
 | 
|  
 | 
|      // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
 | 
| @@ -3809,7 +3804,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
 | 
|    Expect(Token::RBRACE, CHECK_OK);
 | 
|  
 | 
|    // Computation of literal_index must happen before pre parse bailout.
 | 
| -  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 | 
| +  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
 | 
|  
 | 
|    Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
 | 
|        number_of_boilerplate_properties * 2, TENURED);
 | 
| @@ -3841,7 +3836,7 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
 | 
|      return NULL;
 | 
|    }
 | 
|  
 | 
| -  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 | 
| +  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
 | 
|  
 | 
|    Handle<String> js_pattern = NextLiteralString(TENURED);
 | 
|    scanner().ScanRegExpFlags();
 | 
| @@ -3909,7 +3904,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
 | 
|    Handle<FixedArray> this_property_assignments;
 | 
|    bool has_duplicate_parameters = false;
 | 
|    // Parse function body.
 | 
| -  { LexicalScope lexical_scope(this, scope, isolate());
 | 
| +  { FunctionState function_state(this, scope, isolate());
 | 
|      top_scope_->SetScopeName(function_name);
 | 
|  
 | 
|      //  FormalParameterList ::
 | 
| @@ -4020,11 +4015,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
 | 
|      if (!is_lazily_compiled) {
 | 
|        ParseSourceElements(body, Token::RBRACE, CHECK_OK);
 | 
|  
 | 
| -      materialized_literal_count = lexical_scope.materialized_literal_count();
 | 
| -      expected_property_count = lexical_scope.expected_property_count();
 | 
| +      materialized_literal_count = function_state.materialized_literal_count();
 | 
| +      expected_property_count = function_state.expected_property_count();
 | 
|        only_simple_this_property_assignments =
 | 
| -          lexical_scope.only_simple_this_property_assignments();
 | 
| -      this_property_assignments = lexical_scope.this_property_assignments();
 | 
| +          function_state.only_simple_this_property_assignments();
 | 
| +      this_property_assignments = function_state.this_property_assignments();
 | 
|  
 | 
|        Expect(Token::RBRACE, CHECK_OK);
 | 
|        scope->set_end_position(scanner().location().end_pos);
 | 
| 
 |