Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Unified Diff: src/preparser.cc

Issue 641283003: Support lazy parsing of inner functions (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: Actually track variable declarations in the preparser Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/preparser.h ('k') | src/vector.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.cc
diff --git a/src/preparser.cc b/src/preparser.cc
index 987900a20d5844ebfef3e17d93fcd4c43f9503ea..e0c0ffd883d27255e4b83be25f6cbdb1b1b22f92 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,74 @@
namespace v8 {
namespace internal {
+PreParserScope::~PreParserScope() {
+ if (unbound_variables_ && outer_scope_) {
+ 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_))) {
+ outer_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) {
+ 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);
+ }
+}
+
+
+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, bool lexical) {
+ if (lexical || is_declaration_scope()) {
+ DCHECK(declared_variables_);
+ declared_variables_->Lookup(const_cast<AstRawString*>(identifier),
+ identifier->hash(), true,
+ ZoneAllocationPolicy(zone_));
+ } else {
+ DeclarationScope()->Declare(identifier, lexical);
+ }
+}
+
+
+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 +111,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 +178,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);
@@ -329,6 +409,12 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
+ if (log_identifiers_) {
+ DCHECK(ast_value_factory_);
+ const AstRawString* identifier =
+ scanner()->CurrentSymbol(ast_value_factory_);
+ scope_->Declare(identifier);
+ }
ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
@@ -344,6 +430,12 @@ PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
bool is_strict_reserved = false;
Identifier name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+ if (log_identifiers_) {
+ DCHECK(ast_value_factory_);
+ const AstRawString* identifier =
+ scanner()->CurrentSymbol(ast_value_factory_);
+ scope_->Declare(identifier);
+ }
ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
CHECK_OK);
return Statement::Default();
@@ -358,10 +450,14 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
// (ECMA-262, 3rd, 12.2)
//
Expect(Token::LBRACE, CHECK_OK);
- while (peek() != Token::RBRACE) {
- if (allow_harmony_scoping() && strict_mode() == STRICT) {
+ if (allow_harmony_scoping() && strict_mode() == STRICT) {
+ PreParserScope block_scope = NewScope(scope_, BLOCK_SCOPE);
+ BlockState block_state(&scope_, &block_scope);
+ while (peek() != Token::RBRACE) {
ParseSourceElement(CHECK_OK);
- } else {
+ }
+ } else {
+ while (peek() != Token::RBRACE) {
ParseStatement(CHECK_OK);
}
}
@@ -409,6 +505,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
// ConstBinding ::
// BindingPattern '=' AssignmentExpression
bool require_initializer = false;
+ bool lexical = false;
if (peek() == Token::VAR) {
Consume(Token::VAR);
} else if (peek() == Token::CONST) {
@@ -431,6 +528,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
return Statement::Default();
}
require_initializer = true;
+ lexical = true;
} else {
Scanner::Location location = scanner()->peek_location();
ReportMessageAt(location, "strict_const");
@@ -445,6 +543,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
*ok = false;
return Statement::Default();
}
+ lexical = true;
} else {
*ok = false;
return Statement::Default();
@@ -459,6 +558,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, lexical);
+ }
nvars++;
if (peek() == Token::ASSIGN || require_initializer) {
Expect(Token::ASSIGN, CHECK_OK);
@@ -593,7 +698,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();
@@ -673,6 +778,11 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
// ForStatement ::
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
+ // Create an in-between scope for let-bound iteration variables.
+ PreParserScope* saved_scope = scope_;
+ PreParserScope for_scope = NewScope(scope_, BLOCK_SCOPE);
+ scope_ = &for_scope;
+
Expect(Token::FOR, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
if (peek() != Token::SEMICOLON) {
@@ -687,10 +797,14 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
bool accept_OF = !has_initializers;
if (accept_IN && CheckInOrOf(accept_OF)) {
+ // The expression does not see the loop variable.
+ scope_ = saved_scope;
ParseExpression(true, CHECK_OK);
+ scope_ = &for_scope;
Expect(Token::RPAREN, CHECK_OK);
ParseStatement(CHECK_OK);
+ scope_ = saved_scope;
return Statement::Default();
}
} else {
@@ -700,6 +814,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
ParseStatement(CHECK_OK);
+ scope_ = saved_scope;
return Statement::Default();
}
}
@@ -719,6 +834,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
ParseStatement(ok);
+ scope_ = saved_scope;
return Statement::Default();
}
@@ -765,9 +881,15 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
Consume(Token::CATCH);
Expect(Token::LPAREN, CHECK_OK);
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ if (log_identifiers_) {
+ DCHECK(ast_value_factory_);
+ const AstRawString* identifier =
+ scanner()->CurrentSymbol(ast_value_factory_);
+ scope_->Declare(identifier);
+ }
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 +934,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);
@@ -836,6 +958,12 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
bool is_strict_reserved = false;
Identifier param_name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+ if (log_identifiers_) {
+ DCHECK(ast_value_factory_);
+ const AstRawString* identifier =
+ scanner()->CurrentSymbol(ast_value_factory_);
+ scope_->Declare(identifier);
+ }
if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
eval_args_error_loc = scanner()->location();
}
@@ -915,6 +1043,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(),
« no previous file with comments | « src/preparser.h ('k') | src/vector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698