Commit 10ae9eb2 authored by marja@chromium.org's avatar marja@chromium.org

Refactor scope and function state tracking in (Pre)Parser.

Notes:
- PreParser::Scope was a weird combination of Parser::FunctionState and
  Scope. Split it into two (PreParser::FunctionState and PreParser::Scope). This
  is necessary for unifying the Parser and the PreParser.
- Scopes take care of language mode and tracking "with".
- FunctionStates take care of counting material literal indexes, properties
  etc. and tracking generators.
- PreParser::Scope::InsideWith was a hack to make a FunctionState-like object
  take care of tracking "with". It's now the responsibility fo PreParser::Scope
  and Scope.
- PreParser::ScopeType is unnecessarly, there is already a ScopeType enum in
v8globals.h.
- Renamed scope stack variables so that they're consistent in Parser and PreParser.
- Parser::FunctionState and Parser::BlockState had an unnecessary dependency to
  the Parser; they only need a couple of things from Parser. Broke the
  dependency.

R=ulan@chromium.org
BUG=v8:3126
LOG=N

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19319 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 96a18866
This diff is collapsed.
...@@ -498,7 +498,9 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -498,7 +498,9 @@ class Parser : public ParserBase<ParserTraits> {
class FunctionState BASE_EMBEDDED { class FunctionState BASE_EMBEDDED {
public: public:
FunctionState(Parser* parser, Scope* scope); FunctionState(FunctionState** function_state_stack,
Scope** scope_stack, Scope* scope,
Zone* zone);
~FunctionState(); ~FunctionState();
int NextMaterializedLiteralIndex() { int NextMaterializedLiteralIndex() {
...@@ -545,9 +547,11 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -545,9 +547,11 @@ class Parser : public ParserBase<ParserTraits> {
// indicates that this function is not a generator. // indicates that this function is not a generator.
Variable* generator_object_variable_; Variable* generator_object_variable_;
Parser* parser_; FunctionState** function_state_stack_;
FunctionState* outer_function_state_; FunctionState* outer_function_state_;
Scope** scope_stack_;
Scope* outer_scope_; Scope* outer_scope_;
Isolate* isolate_;
int saved_ast_node_id_; int saved_ast_node_id_;
AstNodeFactory<AstConstructionVisitor> factory_; AstNodeFactory<AstConstructionVisitor> factory_;
}; };
...@@ -590,17 +594,17 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -590,17 +594,17 @@ class Parser : public ParserBase<ParserTraits> {
symbol_cache_.Initialize(data ? data->symbol_count() : 0, zone()); symbol_cache_.Initialize(data ? data->symbol_count() : 0, zone());
} }
bool inside_with() const { return top_scope_->inside_with(); } bool inside_with() const { return scope_->inside_with(); }
Scanner& scanner() { return scanner_; } Scanner& scanner() { return scanner_; }
Mode mode() const { return mode_; } Mode mode() const { return mode_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; } ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
bool is_extended_mode() { bool is_extended_mode() {
ASSERT(top_scope_ != NULL); ASSERT(scope_ != NULL);
return top_scope_->is_extended_mode(); return scope_->is_extended_mode();
} }
Scope* DeclarationScope(VariableMode mode) { Scope* DeclarationScope(VariableMode mode) {
return IsLexicalVariableMode(mode) return IsLexicalVariableMode(mode)
? top_scope_ : top_scope_->DeclarationScope(); ? scope_ : scope_->DeclarationScope();
} }
// All ParseXXX functions take as the last argument an *ok parameter // All ParseXXX functions take as the last argument an *ok parameter
...@@ -767,7 +771,7 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -767,7 +771,7 @@ class Parser : public ParserBase<ParserTraits> {
SingletonLogger* logger); SingletonLogger* logger);
AstNodeFactory<AstConstructionVisitor>* factory() { AstNodeFactory<AstConstructionVisitor>* factory() {
return current_function_state_->factory(); return function_state_->factory();
} }
Isolate* isolate_; Isolate* isolate_;
...@@ -776,9 +780,9 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -776,9 +780,9 @@ class Parser : public ParserBase<ParserTraits> {
Handle<Script> script_; Handle<Script> script_;
Scanner scanner_; Scanner scanner_;
PreParser* reusable_preparser_; PreParser* reusable_preparser_;
Scope* top_scope_; Scope* scope_; // Scope stack.
Scope* original_scope_; // for ES5 function declarations in sloppy eval Scope* original_scope_; // for ES5 function declarations in sloppy eval
FunctionState* current_function_state_; FunctionState* function_state_; // Function state stack.
Target* target_stack_; // for break, continue statements Target* target_stack_; // for break, continue statements
v8::Extension* extension_; v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_; ScriptDataImpl* pre_parse_data_;
...@@ -788,8 +792,6 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -788,8 +792,6 @@ class Parser : public ParserBase<ParserTraits> {
Zone* zone_; Zone* zone_;
CompilationInfo* info_; CompilationInfo* info_;
friend class BlockState;
friend class FunctionState;
}; };
......
...@@ -61,12 +61,12 @@ bool PreParserTraits::is_classic_mode() const { ...@@ -61,12 +61,12 @@ bool PreParserTraits::is_classic_mode() const {
bool PreParserTraits::is_generator() const { bool PreParserTraits::is_generator() const {
return pre_parser_->scope_->is_generator(); return pre_parser_->function_state_->is_generator();
} }
int PreParserTraits::NextMaterializedLiteralIndex() { int PreParserTraits::NextMaterializedLiteralIndex() {
return pre_parser_->scope_->NextMaterializedLiteralIndex(); return pre_parser_->function_state_->NextMaterializedLiteralIndex();
} }
...@@ -126,9 +126,9 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( ...@@ -126,9 +126,9 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
LanguageMode mode, bool is_generator, ParserRecorder* log) { LanguageMode mode, bool is_generator, ParserRecorder* log) {
log_ = log; log_ = log;
// Lazy functions always have trivial outer scopes (no with/catch scopes). // Lazy functions always have trivial outer scopes (no with/catch scopes).
Scope top_scope(&scope_, kTopLevelScope); FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE);
set_language_mode(mode); scope_->SetLanguageMode(mode);
Scope function_scope(&scope_, kFunctionScope); FunctionState function_scope(&function_state_, &scope_, FUNCTION_SCOPE);
function_scope.set_is_generator(is_generator); function_scope.set_is_generator(is_generator);
ASSERT_EQ(Token::LBRACE, scanner()->current_token()); ASSERT_EQ(Token::LBRACE, scanner()->current_token());
bool ok = true; bool ok = true;
...@@ -206,8 +206,8 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token, ...@@ -206,8 +206,8 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
Statement statement = ParseSourceElement(CHECK_OK); Statement statement = ParseSourceElement(CHECK_OK);
if (directive_prologue) { if (directive_prologue) {
if (statement.IsUseStrictLiteral()) { if (statement.IsUseStrictLiteral()) {
set_language_mode(allow_harmony_scoping() ? scope_->SetLanguageMode(allow_harmony_scoping() ?
EXTENDED_MODE : STRICT_MODE); EXTENDED_MODE : STRICT_MODE);
} else if (!statement.IsStringLiteral()) { } else if (!statement.IsStringLiteral()) {
directive_prologue = false; directive_prologue = false;
} }
...@@ -352,7 +352,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { ...@@ -352,7 +352,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
// //
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) { while (peek() != Token::RBRACE) {
if (is_extended_mode()) { if (scope_->is_extended_mode()) {
ParseSourceElement(CHECK_OK); ParseSourceElement(CHECK_OK);
} else { } else {
ParseStatement(CHECK_OK); ParseStatement(CHECK_OK);
...@@ -416,7 +416,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -416,7 +416,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
// existing pages. Therefore we keep allowing const with the old // existing pages. Therefore we keep allowing const with the old
// non-harmony semantics in classic mode. // non-harmony semantics in classic mode.
Consume(Token::CONST); Consume(Token::CONST);
switch (language_mode()) { switch (scope_->language_mode()) {
case CLASSIC_MODE: case CLASSIC_MODE:
break; break;
case STRICT_MODE: { case STRICT_MODE: {
...@@ -442,7 +442,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -442,7 +442,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
// //
// * It is a Syntax Error if the code that matches this production is not // * It is a Syntax Error if the code that matches this production is not
// contained in extended code. // contained in extended code.
if (!is_extended_mode()) { if (!scope_->is_extended_mode()) {
ReportMessageAt(scanner()->peek_location(), "illegal_let"); ReportMessageAt(scanner()->peek_location(), "illegal_let");
*ok = false; *ok = false;
return Statement::Default(); return Statement::Default();
...@@ -602,7 +602,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { ...@@ -602,7 +602,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
ParseExpression(true, CHECK_OK); ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
Scope::InsideWith iw(scope_); BlockState block_state(&scope_, WITH_SCOPE);
ParseStatement(CHECK_OK); ParseStatement(CHECK_OK);
return Statement::Default(); return Statement::Default();
} }
...@@ -775,7 +775,8 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { ...@@ -775,7 +775,8 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
{ Scope::InsideWith iw(scope_); {
BlockState block_state(&scope_, WITH_SCOPE);
ParseBlock(CHECK_OK); ParseBlock(CHECK_OK);
} }
tok = peek(); tok = peek();
...@@ -833,7 +834,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, ...@@ -833,7 +834,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
// YieldExpression // YieldExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression // LeftHandSideExpression AssignmentOperator AssignmentExpression
if (scope_->is_generator() && peek() == Token::YIELD) { if (function_state_->is_generator() && peek() == Token::YIELD) {
return ParseYieldExpression(ok); return ParseYieldExpression(ok);
} }
...@@ -859,7 +860,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, ...@@ -859,7 +860,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
ParseAssignmentExpression(accept_IN, CHECK_OK); ParseAssignmentExpression(accept_IN, CHECK_OK);
if ((op == Token::ASSIGN) && expression.IsThisProperty()) { if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
scope_->AddProperty(); function_state_->AddProperty();
} }
return Expression::Default(); return Expression::Default();
...@@ -1219,7 +1220,7 @@ PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { ...@@ -1219,7 +1220,7 @@ PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
} }
Expect(Token::RBRACK, CHECK_OK); Expect(Token::RBRACK, CHECK_OK);
scope_->NextMaterializedLiteralIndex(); function_state_->NextMaterializedLiteralIndex();
return Expression::Default(); return Expression::Default();
} }
...@@ -1231,7 +1232,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1231,7 +1232,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
// )*[','] '}' // )*[','] '}'
ObjectLiteralChecker checker(this, language_mode()); ObjectLiteralChecker checker(this, scope_->language_mode());
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) { while (peek() != Token::RBRACE) {
...@@ -1301,7 +1302,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1301,7 +1302,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
} }
Expect(Token::RBRACE, CHECK_OK); Expect(Token::RBRACE, CHECK_OK);
scope_->NextMaterializedLiteralIndex(); function_state_->NextMaterializedLiteralIndex();
return Expression::Default(); return Expression::Default();
} }
...@@ -1339,8 +1340,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -1339,8 +1340,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// Parse function body. // Parse function body.
ScopeType outer_scope_type = scope_->type(); ScopeType outer_scope_type = scope_->type();
bool inside_with = scope_->IsInsideWith(); bool inside_with = scope_->inside_with();
Scope function_scope(&scope_, kFunctionScope); FunctionState function_scope(&function_state_, &scope_, FUNCTION_SCOPE);
function_scope.set_is_generator(is_generator); function_scope.set_is_generator(is_generator);
// FormalParameterList :: // FormalParameterList ::
// '(' (Identifier)*[','] ')' // '(' (Identifier)*[','] ')'
...@@ -1388,7 +1389,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -1388,7 +1389,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// Determine if the function will be lazily compiled. // Determine if the function will be lazily compiled.
// Currently only happens to top-level functions. // Currently only happens to top-level functions.
// Optimistically assume that all top-level functions are lazily compiled. // Optimistically assume that all top-level functions are lazily compiled.
bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && bool is_lazily_compiled = (outer_scope_type == GLOBAL_SCOPE &&
!inside_with && allow_lazy() && !inside_with && allow_lazy() &&
!parenthesized_function_); !parenthesized_function_);
parenthesized_function_ = false; parenthesized_function_ = false;
...@@ -1450,9 +1451,9 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { ...@@ -1450,9 +1451,9 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
ASSERT_EQ(Token::RBRACE, scanner()->peek()); ASSERT_EQ(Token::RBRACE, scanner()->peek());
int body_end = scanner()->peek_location().end_pos; int body_end = scanner()->peek_location().end_pos;
log_->LogFunction(body_start, body_end, log_->LogFunction(body_start, body_end,
scope_->materialized_literal_count(), function_state_->materialized_literal_count(),
scope_->expected_properties(), function_state_->expected_properties(),
language_mode()); scope_->language_mode());
} }
......
...@@ -512,6 +512,7 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -512,6 +512,7 @@ class PreParser : public ParserBase<PreParserTraits> {
uintptr_t stack_limit) uintptr_t stack_limit)
: ParserBase<PreParserTraits>(scanner, stack_limit, this), : ParserBase<PreParserTraits>(scanner, stack_limit, this),
log_(log), log_(log),
function_state_(NULL),
scope_(NULL) { } scope_(NULL) { }
~PreParser() {} ~PreParser() {}
...@@ -521,7 +522,7 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -521,7 +522,7 @@ class PreParser : public ParserBase<PreParserTraits> {
// captured the syntax error), and false if a stack-overflow happened // captured the syntax error), and false if a stack-overflow happened
// during parsing. // during parsing.
PreParseResult PreParseProgram() { PreParseResult PreParseProgram() {
Scope top_scope(&scope_, kTopLevelScope); FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE);
bool ok = true; bool ok = true;
int start_position = scanner()->peek_location().beg_pos; int start_position = scanner()->peek_location().beg_pos;
ParseSourceElements(Token::EOS, &ok); ParseSourceElements(Token::EOS, &ok);
...@@ -554,11 +555,6 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -554,11 +555,6 @@ class PreParser : public ParserBase<PreParserTraits> {
// are either being counted in the preparser data, or is important // are either being counted in the preparser data, or is important
// to throw the correct syntax error exceptions. // to throw the correct syntax error exceptions.
enum ScopeType {
kTopLevelScope,
kFunctionScope
};
enum VariableDeclarationContext { enum VariableDeclarationContext {
kSourceElement, kSourceElement,
kStatement, kStatement,
...@@ -626,61 +622,97 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -626,61 +622,97 @@ class PreParser : public ParserBase<PreParserTraits> {
class Scope { class Scope {
public: public:
Scope(Scope** variable, ScopeType type) explicit Scope(Scope* outer_scope, ScopeType scope_type)
: variable_(variable), : scope_type_(scope_type) {
prev_(*variable), if (outer_scope) {
type_(type), scope_inside_with_ =
outer_scope->scope_inside_with_ || is_with_scope();
language_mode_ = outer_scope->language_mode();
} else {
scope_inside_with_ = is_with_scope();
language_mode_ = CLASSIC_MODE;
}
}
bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
bool is_classic_mode() const {
return language_mode() == CLASSIC_MODE;
}
bool is_extended_mode() {
return language_mode() == EXTENDED_MODE;
}
bool inside_with() const {
return scope_inside_with_;
}
ScopeType type() { return scope_type_; }
LanguageMode language_mode() const { return language_mode_; }
void SetLanguageMode(LanguageMode language_mode) {
language_mode_ = language_mode;
}
private:
ScopeType scope_type_;
bool scope_inside_with_;
LanguageMode language_mode_;
};
class FunctionState {
public:
FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
ScopeType scope_type)
: function_state_stack_(function_state_stack),
outer_function_state_(*function_state_stack),
scope_stack_(scope_stack),
outer_scope_(*scope_stack),
scope_(*scope_stack, scope_type),
materialized_literal_count_(0), materialized_literal_count_(0),
expected_properties_(0), expected_properties_(0),
with_nesting_count_(0),
language_mode_(
(prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
is_generator_(false) { is_generator_(false) {
*variable = this; *scope_stack = &scope_;
*function_state_stack = this;
}
~FunctionState() {
*scope_stack_ = outer_scope_;
*function_state_stack_ = outer_function_state_;
} }
~Scope() { *variable_ = prev_; }
int NextMaterializedLiteralIndex() { return materialized_literal_count_++; } int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
void AddProperty() { expected_properties_++; } void AddProperty() { expected_properties_++; }
ScopeType type() { return type_; }
int expected_properties() { return expected_properties_; } int expected_properties() { return expected_properties_; }
int materialized_literal_count() { return materialized_literal_count_; } int materialized_literal_count() { return materialized_literal_count_; }
bool IsInsideWith() { return with_nesting_count_ != 0; }
bool is_generator() { return is_generator_; } bool is_generator() { return is_generator_; }
void set_is_generator(bool is_generator) { is_generator_ = is_generator; } void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
bool is_classic_mode() {
return language_mode_ == CLASSIC_MODE;
}
LanguageMode language_mode() {
return language_mode_;
}
void set_language_mode(LanguageMode language_mode) {
language_mode_ = language_mode;
}
class InsideWith {
public:
explicit InsideWith(Scope* scope) : scope_(scope) {
scope->with_nesting_count_++;
}
~InsideWith() { scope_->with_nesting_count_--; }
private:
Scope* scope_;
DISALLOW_COPY_AND_ASSIGN(InsideWith);
};
private: private:
Scope** const variable_; FunctionState** const function_state_stack_;
Scope* const prev_; FunctionState* const outer_function_state_;
const ScopeType type_; Scope** const scope_stack_;
Scope* const outer_scope_;
Scope scope_;
int materialized_literal_count_; int materialized_literal_count_;
int expected_properties_; int expected_properties_;
int with_nesting_count_;
LanguageMode language_mode_; LanguageMode language_mode_;
bool is_generator_; bool is_generator_;
}; };
class BlockState {
public:
BlockState(Scope** scope_stack, ScopeType scope_type)
: scope_stack_(scope_stack),
outer_scope_(*scope_stack),
scope_(*scope_stack, scope_type) {
*scope_stack_ = &scope_;
}
~BlockState() { *scope_stack_ = outer_scope_; }
private:
Scope** scope_stack_;
Scope* outer_scope_;
Scope scope_;
};
// All ParseXXX functions take as the last argument an *ok parameter // All ParseXXX functions take as the last argument an *ok parameter
// which is set to false if parsing failed; it is unchanged otherwise. // which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check // By making the 'exception handling' explicit, we are forced to check
...@@ -740,19 +772,10 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -740,19 +772,10 @@ class PreParser : public ParserBase<PreParserTraits> {
// Log the currently parsed string literal. // Log the currently parsed string literal.
Expression GetStringSymbol(); Expression GetStringSymbol();
void set_language_mode(LanguageMode language_mode) {
scope_->set_language_mode(language_mode);
}
bool is_extended_mode() {
return scope_->language_mode() == EXTENDED_MODE;
}
LanguageMode language_mode() { return scope_->language_mode(); }
bool CheckInOrOf(bool accept_OF); bool CheckInOrOf(bool accept_OF);
ParserRecorder* log_; ParserRecorder* log_;
FunctionState* function_state_;
Scope* scope_; Scope* scope_;
}; };
......
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