Chromium Code Reviews| Index: src/preparser.cc |
| diff --git a/src/preparser.cc b/src/preparser.cc |
| index 987900a20d5844ebfef3e17d93fcd4c43f9503ea..84177513d7b2a463f229a217beeed54b674735ef 100644 |
| --- a/src/preparser.cc |
| +++ b/src/preparser.cc |
| @@ -11,6 +11,7 @@ |
| #include "src/globals.h" |
| #include "src/hashmap.h" |
| #include "src/list.h" |
| +#include "src/parser.h" |
| #include "src/preparse-data.h" |
| #include "src/preparse-data-format.h" |
| #include "src/preparser.h" |
| @@ -20,6 +21,79 @@ |
| namespace v8 { |
| namespace internal { |
| +PreParserScope::~PreParserScope() { |
| + if (unbound_variables_ && outer_scope_) { |
| + PreParserScope* scope = outer_scope_->DeclarationScope(); |
| + for (ZoneHashMap::Entry* p = unbound_variables_->Start(); p != NULL; |
| + p = unbound_variables_->Next(p)) { |
| + AstRawString* identifier = static_cast<AstRawString*>(p->key); |
| + if (!declared_variables_->Lookup(identifier, identifier->hash(), false, |
| + ZoneAllocationPolicy(zone_))) { |
| + scope->RecordVariableUsage(identifier); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| +PreParserScope* PreParserScope::DeclarationScope() { |
| + PreParserScope* scope = this; |
| + while (!scope->is_declaration_scope()) { |
| + scope = scope->outer_scope(); |
| + } |
| + return scope; |
| +} |
| + |
| + |
| +void PreParserScope::RecordVariableUsage(const AstRawString* identifier) { |
| + if (is_declaration_scope()) { |
| + ZoneAllocationPolicy allocator(zone_); |
| + if (!declared_variables_->Lookup(const_cast<AstRawString*>(identifier), |
| + identifier->hash(), false, allocator)) { |
| + unbound_variables_->Lookup(const_cast<AstRawString*>(identifier), |
| + identifier->hash(), true, allocator); |
| + } |
| + } else { |
| + DeclarationScope()->Declare(identifier); |
|
rossberg
2014/11/06 11:55:46
Why Declare here?
|
| + } |
| +} |
| + |
| + |
| +void PreParserScope::LogUnboundVariables(ParserRecorder* recorder) { |
| + for (ZoneHashMap::Entry* p = unbound_variables_->Start(); p != NULL; |
| + p = unbound_variables_->Next(p)) { |
| + AstRawString* identifier = static_cast<AstRawString*>(p->key); |
| + if (!declared_variables_->Lookup(identifier, identifier->hash(), false, |
| + ZoneAllocationPolicy(zone_))) { |
| + recorder->LogIdentifier(identifier); |
| + } |
| + } |
| + unbound_variables_->Clear(); |
| +} |
| + |
| + |
| +void PreParserScope::Declare(const AstRawString* identifier) { |
| + if (is_declaration_scope()) { |
| + DCHECK(declared_variables_); |
| + declared_variables_->Lookup(const_cast<AstRawString*>(identifier), |
| + identifier->hash(), true, |
| + ZoneAllocationPolicy(zone_)); |
| + } else { |
| + DeclarationScope()->Declare(identifier); |
| + } |
| +} |
| + |
| + |
| +void PreParserTraits::RecordCurrentSymbolAsIdentifierExpression() { |
| + if (pre_parser_->log_ != NULL && pre_parser_->log_identifiers_) { |
| + DCHECK(pre_parser_->ast_value_factory_ != NULL); |
| + const AstRawString* identifier = |
| + pre_parser_->scanner()->CurrentSymbol(pre_parser_->ast_value_factory_); |
| + pre_parser_->scope_->RecordVariableUsage(identifier); |
| + } |
| +} |
| + |
| + |
| void PreParserTraits::ReportMessageAt(Scanner::Location location, |
| const char* message, |
| const char* arg, |
| @@ -42,6 +116,15 @@ void PreParserTraits::ReportMessageAt(int start_pos, |
| } |
| +void PreParserTraits::CheckPossibleEvalCall(PreParserExpression expression, |
| + PreParserScope* scope) { |
| + if (pre_parser_->log_ != NULL && pre_parser_->log_identifiers_ && |
| + expression.IsIdentifier() && expression.AsIdentifier().IsEval()) { |
| + pre_parser_->log_->LogEvalCall(); |
| + } |
| +} |
| + |
| + |
| PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { |
| if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) { |
| return PreParserIdentifier::FutureReserved(); |
| @@ -100,14 +183,16 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( |
| PreParser::PreParseResult PreParser::PreParseLazyFunction( |
| - StrictMode strict_mode, bool is_generator, ParserRecorder* log) { |
| + StrictMode strict_mode, bool is_generator, bool log_identifiers, |
| + ParserRecorder* log) { |
| + log_identifiers_ = log_identifiers; |
| log_ = log; |
| // Lazy functions always have trivial outer scopes (no with/catch scopes). |
| - PreParserScope top_scope(scope_, GLOBAL_SCOPE); |
| + PreParserScope top_scope = NewScope(NULL, GLOBAL_SCOPE); |
| PreParserFactory top_factory(NULL); |
| FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory); |
| scope_->SetStrictMode(strict_mode); |
| - PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| + PreParserScope function_scope = NewScope(scope_, FUNCTION_SCOPE); |
| PreParserFactory function_factory(NULL); |
| FunctionState function_state(&function_state_, &scope_, &function_scope, |
| &function_factory); |
| @@ -459,6 +544,12 @@ PreParser::Statement PreParser::ParseVariableDeclarations( |
| // Parse variable name. |
| if (nvars > 0) Consume(Token::COMMA); |
| ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| + if (log_identifiers_) { |
| + DCHECK(ast_value_factory_); |
| + const AstRawString* identifier = |
| + scanner()->CurrentSymbol(ast_value_factory_); |
| + scope_->Declare(identifier); |
| + } |
| nvars++; |
| if (peek() == Token::ASSIGN || require_initializer) { |
| Expect(Token::ASSIGN, CHECK_OK); |
| @@ -593,7 +684,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
| ParseExpression(true, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| - PreParserScope with_scope(scope_, WITH_SCOPE); |
| + PreParserScope with_scope = NewScope(scope_, WITH_SCOPE); |
| BlockState block_state(&scope_, &with_scope); |
| ParseStatement(CHECK_OK); |
| return Statement::Default(); |
| @@ -767,7 +858,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
| ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| { |
| - PreParserScope with_scope(scope_, WITH_SCOPE); |
| + PreParserScope with_scope = NewScope(scope_, WITH_SCOPE); |
| BlockState block_state(&scope_, &with_scope); |
| ParseBlock(CHECK_OK); |
| } |
| @@ -812,7 +903,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( |
| // Parse function body. |
| ScopeType outer_scope_type = scope_->type(); |
| - PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| + PreParserScope function_scope = NewScope(scope_, FUNCTION_SCOPE); |
| PreParserFactory factory(NULL); |
| FunctionState function_state(&function_state_, &scope_, &function_scope, |
| &factory); |
| @@ -915,6 +1006,9 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
| // Position right after terminal '}'. |
| DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| int body_end = scanner()->peek_location().end_pos; |
| + if (log_identifiers_) { |
| + scope_->LogUnboundVariables(log_); |
| + } |
| log_->LogFunction(body_start, body_end, |
| function_state_->materialized_literal_count(), |
| function_state_->expected_property_count(), |