summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing/parser.cc')
-rw-r--r--deps/v8/src/parsing/parser.cc601
1 files changed, 298 insertions, 303 deletions
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index 7b88695e77..8d8890129f 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -68,7 +68,6 @@ bool ParseData::IsSane() {
if (data_length < PreparseDataConstants::kHeaderSize) return false;
if (Magic() != PreparseDataConstants::kMagicNumber) return false;
if (Version() != PreparseDataConstants::kCurrentVersion) return false;
- if (HasError()) return false;
// Check that the space allocated for function entries is sane.
int functions_size = FunctionsSize();
if (functions_size < 0) return false;
@@ -90,11 +89,6 @@ void ParseData::Initialize() {
}
-bool ParseData::HasError() {
- return Data()[PreparseDataConstants::kHasErrorOffset];
-}
-
-
unsigned ParseData::Magic() {
return Data()[PreparseDataConstants::kMagicOffset];
}
@@ -124,6 +118,7 @@ class DiscardableZoneScope {
parser_->zone_ = temp_zone;
if (parser_->reusable_preparser_ != nullptr) {
parser_->reusable_preparser_->zone_ = temp_zone;
+ parser_->reusable_preparser_->factory()->set_zone(temp_zone);
}
}
}
@@ -132,6 +127,7 @@ class DiscardableZoneScope {
parser_->zone_ = prev_zone_;
if (parser_->reusable_preparser_ != nullptr) {
parser_->reusable_preparser_->zone_ = prev_zone_;
+ parser_->reusable_preparser_->factory()->set_zone(prev_zone_);
}
ast_node_factory_scope_.Reset();
}
@@ -148,12 +144,11 @@ class DiscardableZoneScope {
};
void Parser::SetCachedData(ParseInfo* info) {
- if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
- cached_parse_data_ = NULL;
- } else {
- DCHECK(info->cached_data() != NULL);
- if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
- cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
+ DCHECK_NULL(cached_parse_data_);
+ if (consume_cached_parse_data()) {
+ cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
+ if (cached_parse_data_ == nullptr) {
+ compile_options_ = ScriptCompiler::kNoCompileOptions;
}
}
}
@@ -219,7 +214,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
LanguageMode language_mode) {
int materialized_literal_count = -1;
int expected_property_count = -1;
- int parameter_count = 0;
+ const int parameter_count = 0;
if (name == nullptr) name = ast_value_factory()->empty_string();
FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
@@ -282,59 +277,16 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
name, function_scope, body, materialized_literal_count,
- expected_property_count, parameter_count,
+ expected_property_count, parameter_count, parameter_count,
FunctionLiteral::kNoDuplicateParameters,
- FunctionLiteral::kAnonymousExpression,
- FunctionLiteral::kShouldLazyCompile, pos);
+ FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos,
+ true);
function_literal->set_requires_class_field_init(requires_class_field_init);
return function_literal;
}
-
-// ----------------------------------------------------------------------------
-// Target is a support class to facilitate manipulation of the
-// Parser's target_stack_ (the stack of potential 'break' and
-// 'continue' statement targets). Upon construction, a new target is
-// added; it is removed upon destruction.
-
-class ParserTarget BASE_EMBEDDED {
- public:
- ParserTarget(ParserBase<Parser>* parser, BreakableStatement* statement)
- : variable_(&parser->impl()->target_stack_),
- statement_(statement),
- previous_(parser->impl()->target_stack_) {
- parser->impl()->target_stack_ = this;
- }
-
- ~ParserTarget() { *variable_ = previous_; }
-
- ParserTarget* previous() { return previous_; }
- BreakableStatement* statement() { return statement_; }
-
- private:
- ParserTarget** variable_;
- BreakableStatement* statement_;
- ParserTarget* previous_;
-};
-
-class ParserTargetScope BASE_EMBEDDED {
- public:
- explicit ParserTargetScope(ParserBase<Parser>* parser)
- : variable_(&parser->impl()->target_stack_),
- previous_(parser->impl()->target_stack_) {
- parser->impl()->target_stack_ = nullptr;
- }
-
- ~ParserTargetScope() { *variable_ = previous_; }
-
- private:
- ParserTarget** variable_;
- ParserTarget* previous_;
-};
-
-
// ----------------------------------------------------------------------------
// The CHECK_OK macro is a convenient macro to enforce error
// handling for functions that may fail (by returning !*ok).
@@ -521,9 +473,7 @@ Expression* Parser::NewSuperCallReference(int pos) {
}
Expression* Parser::NewTargetExpression(int pos) {
- static const int kNewTargetStringLength = 10;
- auto proxy = NewUnresolved(ast_value_factory()->new_target_string(), pos,
- pos + kNewTargetStringLength);
+ auto proxy = NewUnresolved(ast_value_factory()->new_target_string(), pos);
proxy->set_is_new_target();
return proxy;
}
@@ -547,7 +497,7 @@ Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
case Token::FALSE_LITERAL:
return factory()->NewBooleanLiteral(false, pos);
case Token::SMI: {
- int value = scanner()->smi_value();
+ uint32_t value = scanner()->smi_value();
return factory()->NewSmiLiteral(value, pos);
}
case Token::NUMBER: {
@@ -631,31 +581,48 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
- info->extension(), info->ast_value_factory(), NULL),
+ info->extension(), info->ast_value_factory(),
+ info->isolate()->counters()->runtime_call_stats()),
scanner_(info->unicode_cache()),
- reusable_preparser_(NULL),
- original_scope_(NULL),
- target_stack_(NULL),
+ reusable_preparser_(nullptr),
+ original_scope_(nullptr),
+ mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
+ target_stack_(nullptr),
compile_options_(info->compile_options()),
- cached_parse_data_(NULL),
+ cached_parse_data_(nullptr),
total_preparse_skipped_(0),
- pre_parse_timer_(NULL),
- parsing_on_main_thread_(true) {
+ parsing_on_main_thread_(true),
+ log_(nullptr) {
// Even though we were passed ParseInfo, we should not store it in
// Parser - this makes sure that Isolate is not accidentally accessed via
// ParseInfo during background parsing.
DCHECK(!info->script().is_null() || info->source_stream() != nullptr ||
info->character_stream() != nullptr);
+ // Determine if functions can be lazily compiled. This is necessary to
+ // allow some of our builtin JS files to be lazily compiled. These
+ // builtins cannot be handled lazily by the parser, since we have to know
+ // if a function uses the special natives syntax, which is something the
+ // parser records.
+ // If the debugger requests compilation for break points, we cannot be
+ // aggressive about lazy compilation, because it might trigger compilation
+ // of functions without an outer context when setting a breakpoint through
+ // Debug::FindSharedFunctionInfoInScript
+ bool can_compile_lazily = FLAG_lazy && !info->is_debug();
+
+ // Consider compiling eagerly when targeting the code cache.
+ can_compile_lazily &= !(FLAG_serialize_eager && info->will_serialize());
+
+ set_default_eager_compile_hint(can_compile_lazily
+ ? FunctionLiteral::kShouldLazyCompile
+ : FunctionLiteral::kShouldEagerCompile);
set_allow_lazy(FLAG_lazy && info->allow_lazy_parsing() &&
- !info->is_native() && info->extension() == nullptr);
+ !info->is_native() && info->extension() == nullptr &&
+ can_compile_lazily);
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
info->isolate()->is_tail_call_elimination_enabled());
set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
- set_allow_harmony_for_in(FLAG_harmony_for_in);
set_allow_harmony_function_sent(FLAG_harmony_function_sent);
- set_allow_harmony_restrictive_declarations(
- FLAG_harmony_restrictive_declarations);
set_allow_harmony_async_await(FLAG_harmony_async_await);
set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
@@ -699,9 +666,10 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
// called in the main thread.
DCHECK(parsing_on_main_thread_);
- HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
- RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse);
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.Parse");
+ RuntimeCallTimerScope runtime_timer(
+ runtime_call_stats_, info->is_eval() ? &RuntimeCallStats::ParseEval
+ : &RuntimeCallStats::ParseProgram);
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram");
Handle<String> source(String::cast(info->script()->source()));
isolate->counters()->total_parse_size()->Increment(source->length());
base::ElapsedTimer timer;
@@ -711,10 +679,10 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
// Initialize parser state.
- CompleteParserRecorder recorder;
+ ParserLogger logger;
if (produce_cached_parse_data()) {
- log_ = &recorder;
+ log_ = &logger;
} else if (consume_cached_parse_data()) {
cached_parse_data_->Initialize();
}
@@ -734,7 +702,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
}
HandleSourceURLComments(isolate, info->script());
- if (FLAG_trace_parse && result != NULL) {
+ if (FLAG_trace_parse && result != nullptr) {
double ms = timer.Elapsed().InMillisecondsF();
if (info->is_eval()) {
PrintF("[parsing eval");
@@ -747,10 +715,10 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
}
PrintF(" - took %0.3f ms]\n", ms);
}
- if (produce_cached_parse_data()) {
- if (result != NULL) *info->cached_data() = recorder.GetScriptData();
- log_ = NULL;
+ if (produce_cached_parse_data() && result != nullptr) {
+ *info->cached_data() = logger.GetScriptData();
}
+ log_ = nullptr;
return result;
}
@@ -762,7 +730,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
DCHECK_NULL(scope_state_);
DCHECK_NULL(target_stack_);
- Mode parsing_mode = allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
+ ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
FunctionLiteral* result = NULL;
{
@@ -770,25 +738,16 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
DCHECK_NOT_NULL(outer);
parsing_module_ = info->is_module();
if (info->is_eval()) {
- if (!outer->is_script_scope() || is_strict(info->language_mode())) {
- parsing_mode = PARSE_EAGERLY;
- }
outer = NewEvalScope(outer);
} else if (parsing_module_) {
DCHECK_EQ(outer, info->script_scope());
outer = NewModuleScope(info->script_scope());
- // Never do lazy parsing in modules. If we want to support this in the
- // future, we must force context-allocation for all variables that are
- // declared at the module level but not MODULE-allocated.
- parsing_mode = PARSE_EAGERLY;
}
DeclarationScope* scope = outer->AsDeclarationScope();
scope->set_start_position(0);
- // Enter 'scope' with the given parsing mode.
- ParsingModeScope parsing_mode_scope(this, parsing_mode);
FunctionState function_state(&function_state_, &scope_state_, scope);
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -868,14 +827,13 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
return result;
}
-
-FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
+FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) {
// It's OK to use the Isolate & counters here, since this function is only
// called in the main thread.
DCHECK(parsing_on_main_thread_);
- RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy);
- HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy");
+ RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
+ &RuntimeCallStats::ParseFunction);
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction");
Handle<String> source(String::cast(info->script()->source()));
isolate->counters()->total_parse_size()->Increment(source->length());
base::ElapsedTimer timer;
@@ -892,8 +850,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
source, shared_info->start_position(), shared_info->end_position()));
Handle<String> name(String::cast(shared_info->name()));
- result =
- DoParseLazy(info, ast_value_factory()->GetString(name), stream.get());
+ result = DoParseFunction(info, ast_value_factory()->GetString(name),
+ stream.get());
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
@@ -922,9 +880,9 @@ static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
return FunctionLiteral::kAnonymousExpression;
}
-FunctionLiteral* Parser::DoParseLazy(ParseInfo* info,
- const AstRawString* raw_name,
- Utf16CharacterStream* source) {
+FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
+ const AstRawString* raw_name,
+ Utf16CharacterStream* source) {
scanner_.Initialize(source);
DCHECK_NULL(scope_state_);
DCHECK_NULL(target_stack_);
@@ -1130,15 +1088,19 @@ void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
}
const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
const AstRawString* export_name = NULL;
+ Scanner::Location location = scanner()->location();
if (CheckContextualKeyword(CStrVector("as"))) {
export_name = ParseIdentifierName(CHECK_OK_VOID);
+ // Set the location to the whole "a as b" string, so that it makes sense
+ // both for errors due to "a" and for errors due to "b".
+ location.end_pos = scanner()->location().end_pos;
}
if (export_name == NULL) {
export_name = local_name;
}
export_names->Add(export_name, zone());
local_names->Add(local_name, zone());
- export_locations->Add(scanner()->location(), zone());
+ export_locations->Add(location, zone());
if (peek() == Token::RBRACE) break;
Expect(Token::COMMA, CHECK_OK_VOID);
}
@@ -1168,6 +1130,7 @@ ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
while (peek() != Token::RBRACE) {
const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
const AstRawString* local_name = import_name;
+ Scanner::Location location = scanner()->location();
// In the presence of 'as', the left-side of the 'as' can
// be any IdentifierName. But without 'as', it must be a valid
// BindingIdentifier.
@@ -1188,8 +1151,8 @@ ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
DeclareVariable(local_name, CONST, kNeedsInitialization, position(),
CHECK_OK);
- NamedImport* import = new (zone()) NamedImport(
- import_name, local_name, scanner()->location());
+ NamedImport* import =
+ new (zone()) NamedImport(import_name, local_name, location);
result->Add(import, zone());
if (peek() == Token::RBRACE) break;
@@ -1377,21 +1340,23 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
// 'export' Declaration
// 'export' 'default' ... (handled in ParseExportDefault)
- int pos = peek_position();
Expect(Token::EXPORT, CHECK_OK);
+ int pos = position();
Statement* result = nullptr;
ZoneList<const AstRawString*> names(1, zone());
+ Scanner::Location loc = scanner()->peek_location();
switch (peek()) {
case Token::DEFAULT:
return ParseExportDefault(ok);
case Token::MUL: {
Consume(Token::MUL);
+ loc = scanner()->location();
ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
ExpectSemicolon(CHECK_OK);
- module()->AddStarExport(module_specifier, scanner()->location(), zone());
+ module()->AddStarExport(module_specifier, loc, zone());
return factory()->NewEmptyStatement(pos);
}
@@ -1472,11 +1437,11 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
ReportUnexpectedToken(scanner()->current_token());
return nullptr;
}
+ loc.end_pos = scanner()->location().end_pos;
ModuleDescriptor* descriptor = module();
for (int i = 0; i < names.length(); ++i) {
- // TODO(neis): Provide better location.
- descriptor->AddExport(names[i], names[i], scanner()->location(), zone());
+ descriptor->AddExport(names[i], names[i], loc, zone());
}
DCHECK_NOT_NULL(result);
@@ -1484,13 +1449,12 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
}
VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos,
- int end_pos, VariableKind kind) {
- return scope()->NewUnresolved(factory(), name, begin_pos, end_pos, kind);
+ VariableKind kind) {
+ return scope()->NewUnresolved(factory(), name, begin_pos, kind);
}
VariableProxy* Parser::NewUnresolved(const AstRawString* name) {
- return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos,
- scanner()->location().end_pos);
+ return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos);
}
Declaration* Parser::DeclareVariable(const AstRawString* name,
@@ -1504,18 +1468,19 @@ Declaration* Parser::DeclareVariable(const AstRawString* name,
int pos, bool* ok) {
DCHECK_NOT_NULL(name);
VariableProxy* proxy = factory()->NewVariableProxy(
- name, NORMAL_VARIABLE, scanner()->location().beg_pos,
- scanner()->location().end_pos);
+ name, NORMAL_VARIABLE, scanner()->location().beg_pos);
Declaration* declaration =
factory()->NewVariableDeclaration(proxy, this->scope(), pos);
- Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, CHECK_OK);
+ Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, ok, nullptr,
+ scanner()->location().end_pos);
+ if (!*ok) return nullptr;
return declaration;
}
Variable* Parser::Declare(Declaration* declaration,
DeclarationDescriptor::Kind declaration_kind,
VariableMode mode, InitializationFlag init, bool* ok,
- Scope* scope) {
+ Scope* scope, int var_end_pos) {
if (scope == nullptr) {
scope = this->scope();
}
@@ -1524,11 +1489,18 @@ Variable* Parser::Declare(Declaration* declaration,
declaration, mode, init, allow_harmony_restrictive_generators(),
&sloppy_mode_block_scope_function_redefinition, ok);
if (!*ok) {
+ // If we only have the start position of a proxy, we can't highlight the
+ // whole variable name. Pretend its length is 1 so that we highlight at
+ // least the first character.
+ Scanner::Location loc(declaration->proxy()->position(),
+ var_end_pos != kNoSourcePosition
+ ? var_end_pos
+ : declaration->proxy()->position() + 1);
if (declaration_kind == DeclarationDescriptor::NORMAL) {
- ReportMessage(MessageTemplate::kVarRedeclaration,
- declaration->proxy()->raw_name());
+ ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
+ declaration->proxy()->raw_name());
} else {
- ReportMessage(MessageTemplate::kParamDupe);
+ ReportMessageAt(loc, MessageTemplate::kParamDupe);
}
return nullptr;
}
@@ -1947,7 +1919,6 @@ Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
for_info.parsing_result.declarations[0];
if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) &&
decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
- DCHECK(!allow_harmony_for_in());
++use_counts_[v8::Isolate::kForInInitializer];
const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
VariableProxy* single_var = NewUnresolved(name);
@@ -2034,8 +2005,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
*body_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
(*body_block)->statements()->Add(each_initialization_block, zone());
- *each_variable = factory()->NewVariableProxy(temp, for_info->each_loc.beg_pos,
- for_info->each_loc.end_pos);
+ *each_variable = factory()->NewVariableProxy(temp, for_info->position);
}
// Create a TDZ for any lexically-bound names in for in/of statements.
@@ -2483,7 +2453,7 @@ void Parser::DeclareArrowFunctionFormalParameters(
AddArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos,
CHECK_OK_VOID);
- if (parameters->Arity() > Code::kMaxArguments) {
+ if (parameters->arity > Code::kMaxArguments) {
ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
*ok = false;
return;
@@ -2493,7 +2463,7 @@ void Parser::DeclareArrowFunctionFormalParameters(
if (!parameters->is_simple) {
this->classifier()->RecordNonSimpleParameter();
}
- for (int i = 0; i < parameters->Arity(); ++i) {
+ for (int i = 0; i < parameters->arity; ++i) {
auto parameter = parameters->at(i);
DeclareFormalParameter(parameters->scope, parameter);
if (!this->classifier()
@@ -2551,8 +2521,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
int pos = function_token_pos == kNoSourcePosition ? peek_position()
: function_token_pos;
- bool is_generator = IsGeneratorFunction(kind);
-
// Anonymous functions were passed either the empty symbol or a null
// handle as the function name. Remember if we were passed a non-empty
// handle to decide whether to invoke function name inference.
@@ -2566,7 +2534,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
FunctionLiteral::EagerCompileHint eager_compile_hint =
function_state_->next_function_is_parenthesized()
? FunctionLiteral::kShouldEagerCompile
- : FunctionLiteral::kShouldLazyCompile;
+ : default_eager_compile_hint();
// Determine if the function can be parsed lazily. Lazy parsing is
// different from lazy compilation; we need to parse more eagerly than we
@@ -2600,14 +2568,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// parenthesis before the function means that it will be called
// immediately). bar can be parsed lazily, but we need to parse it in a mode
// that tracks unresolved variables.
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy);
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy());
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr);
+ DCHECK_IMPLIES(parse_lazily(), FLAG_lazy);
+ DCHECK_IMPLIES(parse_lazily(), allow_lazy());
+ DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
+
+ bool can_preparse = parse_lazily() &&
+ eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
bool is_lazy_top_level_function =
- mode() == PARSE_LAZILY &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile &&
- scope()->AllowsLazyParsingWithoutUnresolvedVariables();
+ can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
+
+ RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
+ &RuntimeCallStats::ParseFunctionLiteral);
// Determine whether we can still lazy parse the inner function.
// The preconditions are:
@@ -2629,8 +2601,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// will migrate unresolved variable into a Scope in the main Zone.
// TODO(marja): Refactor parsing modes: simplify this.
bool use_temp_zone =
- allow_lazy() && function_type == FunctionLiteral::kDeclaration &&
- eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
+ (FLAG_lazy_inner_functions
+ ? can_preparse
+ : (is_lazy_top_level_function ||
+ (allow_lazy() && function_type == FunctionLiteral::kDeclaration &&
+ eager_compile_hint == FunctionLiteral::kShouldLazyCompile))) &&
!(FLAG_validate_asm && scope()->IsAsmModule());
bool is_lazy_inner_function =
use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function;
@@ -2638,40 +2613,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// This Scope lives in the main zone. We'll migrate data into that zone later.
DeclarationScope* scope = NewFunctionScope(kind);
SetLanguageMode(scope, language_mode);
+#ifdef DEBUG
+ scope->SetScopeName(function_name);
+#endif
ZoneList<Statement*>* body = nullptr;
- int arity = -1;
int materialized_literal_count = -1;
int expected_property_count = -1;
- DuplicateFinder duplicate_finder(scanner()->unicode_cache());
bool should_be_used_once_hint = false;
- bool has_duplicate_parameters;
-
- FunctionState function_state(&function_state_, &scope_state_, scope);
-#ifdef DEBUG
- scope->SetScopeName(function_name);
-#endif
-
- ExpressionClassifier formals_classifier(this, &duplicate_finder);
-
- if (is_generator) PrepareGeneratorVariables(&function_state);
+ int num_parameters = -1;
+ int function_length = -1;
+ bool has_duplicate_parameters = false;
Expect(Token::LPAREN, CHECK_OK);
- int start_position = scanner()->location().beg_pos;
- this->scope()->set_start_position(start_position);
- ParserFormalParameters formals(scope);
- ParseFormalParameterList(&formals, CHECK_OK);
- arity = formals.Arity();
- Expect(Token::RPAREN, CHECK_OK);
- int formals_end_position = scanner()->location().end_pos;
-
- CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
- formals_end_position, CHECK_OK);
- Expect(Token::LBRACE, CHECK_OK);
- // Don't include the rest parameter into the function's formal parameter
- // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
- // which says whether we need to create an arguments adaptor frame).
- if (formals.has_rest) arity--;
+ scope->set_start_position(scanner()->location().beg_pos);
{
// Temporary zones can nest. When we migrate free variables (see below), we
@@ -2684,26 +2639,25 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// the previous zone is always restored after parsing the body. To be able
// to do scope analysis correctly after full parsing, we migrate needed
// information when the function is parsed.
- Zone temp_zone(zone()->allocator());
+ Zone temp_zone(zone()->allocator(), ZONE_NAME);
DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
#ifdef DEBUG
if (use_temp_zone) scope->set_needs_migration();
#endif
// Eager or lazy parse? If is_lazy_top_level_function, we'll parse
- // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy
- // parsing if it suspects that wasn't a good idea. If so (in which case the
- // parser is expected to have backtracked), or if we didn't try to lazy
- // parse in the first place, we'll have to parse eagerly.
+ // lazily. We'll call SkipFunction, which may decide to
+ // abort lazy parsing if it suspects that wasn't a good idea. If so (in
+ // which case the parser is expected to have backtracked), or if we didn't
+ // try to lazy parse in the first place, we'll have to parse eagerly.
if (is_lazy_top_level_function || is_lazy_inner_function) {
Scanner::BookmarkScope bookmark(scanner());
bookmark.Set();
- LazyParsingResult result = SkipLazyFunctionBody(
- &materialized_literal_count, &expected_property_count,
- is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK);
-
- materialized_literal_count += formals.materialized_literals_count +
- function_state.materialized_literal_count();
+ LazyParsingResult result =
+ SkipFunction(kind, scope, &num_parameters, &function_length,
+ &has_duplicate_parameters, &materialized_literal_count,
+ &expected_property_count, is_lazy_inner_function,
+ is_lazy_top_level_function, CHECK_OK);
if (result == kLazyParsingAborted) {
DCHECK(is_lazy_top_level_function);
@@ -2723,31 +2677,41 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
if (!is_lazy_top_level_function && !is_lazy_inner_function) {
- body = ParseEagerFunctionBody(function_name, pos, formals, kind,
- function_type, CHECK_OK);
-
- materialized_literal_count = function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
+ body = ParseFunction(
+ function_name, pos, kind, function_type, scope, &num_parameters,
+ &function_length, &has_duplicate_parameters,
+ &materialized_literal_count, &expected_property_count, CHECK_OK);
}
- if (use_temp_zone || is_lazy_top_level_function) {
+ DCHECK(use_temp_zone || !is_lazy_top_level_function);
+ if (use_temp_zone) {
// If the preconditions are correct the function body should never be
// accessed, but do this anyway for better behaviour if they're wrong.
body = nullptr;
scope->AnalyzePartially(&previous_zone_ast_node_factory);
}
- // Parsing the body may change the language mode in our scope.
- language_mode = scope->language_mode();
+ if (FLAG_trace_preparse) {
+ PrintF(" [%s]: %i-%i %.*s\n",
+ is_lazy_top_level_function
+ ? "Preparse no-resolution"
+ : (use_temp_zone ? "Preparse resolution" : "Full parse"),
+ scope->start_position(), scope->end_position(),
+ function_name->byte_length(), function_name->raw_data());
+ if (is_lazy_top_level_function) {
+ CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
+ PreParseNoVariableResolution);
+ } else if (use_temp_zone) {
+ CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
+ PreParseWithVariableResolution);
+ }
+ }
- // Validate name and parameter names. We can do this only after parsing the
- // function, since the function can declare itself strict.
+ // Validate function name. We can do this only after parsing the function,
+ // since the function can declare itself strict.
+ language_mode = scope->language_mode();
CheckFunctionName(language_mode, function_name, function_name_validity,
function_name_location, CHECK_OK);
- const bool allow_duplicate_parameters =
- is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
- ValidateFormalParameters(language_mode, allow_duplicate_parameters,
- CHECK_OK);
if (is_strict(language_mode)) {
CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
@@ -2756,13 +2720,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->end_position());
}
CheckConflictingVarDeclarations(scope, CHECK_OK);
-
- if (body) {
- // If body can be inspected, rewrite queued destructuring assignments
- RewriteDestructuringAssignments();
- }
- has_duplicate_parameters =
- !classifier()->is_valid_formal_parameter_list_without_duplicates();
} // DiscardableZoneScope goes out of scope.
FunctionLiteral::ParameterFlag duplicate_parameters =
@@ -2772,8 +2729,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// Note that the FunctionLiteral needs to be created in the main Zone again.
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
function_name, scope, body, materialized_literal_count,
- expected_property_count, arity, duplicate_parameters, function_type,
- eager_compile_hint, pos);
+ expected_property_count, num_parameters, function_length,
+ duplicate_parameters, function_type, eager_compile_hint, pos, true);
function_literal->set_function_token_position(function_token_pos);
if (should_be_used_once_hint)
function_literal->set_should_be_used_once_hint();
@@ -2785,44 +2742,72 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
return function_literal;
}
-Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
+Parser::LazyParsingResult Parser::SkipFunction(
+ FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
+ int* function_length, bool* has_duplicate_parameters,
int* materialized_literal_count, int* expected_property_count,
bool is_inner_function, bool may_abort, bool* ok) {
+ DCHECK_NE(kNoSourcePosition, function_scope->start_position());
if (produce_cached_parse_data()) CHECK(log_);
- int function_block_pos = position();
- DeclarationScope* scope = function_state_->scope();
- DCHECK(scope->is_function_scope());
+ DCHECK_IMPLIES(IsArrowFunction(kind),
+ scanner()->current_token() == Token::ARROW);
+
// Inner functions are not part of the cached data.
if (!is_inner_function && consume_cached_parse_data() &&
!cached_parse_data_->rejected()) {
- // If we have cached data, we use it to skip parsing the function body. The
- // data contains the information we need to construct the lazy function.
+ // If we have cached data, we use it to skip parsing the function. The data
+ // contains the information we need to construct the lazy function.
FunctionEntry entry =
- cached_parse_data_->GetFunctionEntry(function_block_pos);
+ cached_parse_data_->GetFunctionEntry(function_scope->start_position());
// Check that cached data is valid. If not, mark it as invalid (the embedder
// handles it). Note that end position greater than end of stream is safe,
// and hard to check.
- if (entry.is_valid() && entry.end_pos() > function_block_pos) {
+ if (entry.is_valid() &&
+ entry.end_pos() > function_scope->start_position()) {
+ total_preparse_skipped_ += entry.end_pos() - position();
+ function_scope->set_end_position(entry.end_pos());
scanner()->SeekForward(entry.end_pos() - 1);
-
- scope->set_end_position(entry.end_pos());
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
- total_preparse_skipped_ += scope->end_position() - function_block_pos;
+ *num_parameters = entry.num_parameters();
+ *function_length = entry.function_length();
+ *has_duplicate_parameters = entry.has_duplicate_parameters();
*materialized_literal_count = entry.literal_count();
*expected_property_count = entry.property_count();
- SetLanguageMode(scope, entry.language_mode());
- if (entry.uses_super_property()) scope->RecordSuperPropertyUsage();
- if (entry.calls_eval()) scope->RecordEvalCall();
+ SetLanguageMode(function_scope, entry.language_mode());
+ if (entry.uses_super_property())
+ function_scope->RecordSuperPropertyUsage();
+ if (entry.calls_eval()) function_scope->RecordEvalCall();
return kLazyParsingComplete;
}
cached_parse_data_->Reject();
}
+
// With no cached data, we partially parse the function, without building an
// AST. This gathers the data needed to build a lazy function.
- SingletonLogger logger;
- PreParser::PreParseResult result =
- ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort);
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
+
+ if (reusable_preparser_ == NULL) {
+ reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
+ &pending_error_handler_,
+ runtime_call_stats_, stack_limit_);
+ reusable_preparser_->set_allow_lazy(true);
+#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
+ SET_ALLOW(natives);
+ SET_ALLOW(harmony_do_expressions);
+ SET_ALLOW(harmony_function_sent);
+ SET_ALLOW(harmony_async_await);
+ SET_ALLOW(harmony_trailing_commas);
+ SET_ALLOW(harmony_class_fields);
+#undef SET_ALLOW
+ }
+ // Aborting inner function preparsing would leave scopes in an inconsistent
+ // state; we don't parse inner functions in the abortable mode anyway.
+ DCHECK(!is_inner_function || !may_abort);
+
+ PreParser::PreParseResult result = reusable_preparser_->PreParseFunction(
+ kind, function_scope, parsing_module_, is_inner_function, may_abort,
+ use_counts_);
// Return immediately if pre-parser decided to abort parsing.
if (result == PreParser::kPreParseAbort) return kLazyParsingAborted;
@@ -2832,28 +2817,27 @@ Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
*ok = false;
return kLazyParsingComplete;
}
- if (logger.has_error()) {
- ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
- logger.message(), logger.argument_opt(),
- logger.error_type());
+ if (pending_error_handler_.has_pending_error()) {
*ok = false;
return kLazyParsingComplete;
}
- scope->set_end_position(logger.end());
+ PreParserLogger* logger = reusable_preparser_->logger();
+ function_scope->set_end_position(logger->end());
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
- total_preparse_skipped_ += scope->end_position() - function_block_pos;
- *materialized_literal_count = logger.literals();
- *expected_property_count = logger.properties();
- SetLanguageMode(scope, logger.language_mode());
- if (logger.uses_super_property()) scope->RecordSuperPropertyUsage();
- if (logger.calls_eval()) scope->RecordEvalCall();
+ total_preparse_skipped_ +=
+ function_scope->end_position() - function_scope->start_position();
+ *num_parameters = logger->num_parameters();
+ *function_length = logger->function_length();
+ *has_duplicate_parameters = logger->has_duplicate_parameters();
+ *materialized_literal_count = logger->literals();
+ *expected_property_count = logger->properties();
if (!is_inner_function && produce_cached_parse_data()) {
DCHECK(log_);
- // Position right after terminal '}'.
- int body_end = scanner()->location().end_pos;
- log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
- *expected_property_count, language_mode(),
- scope->uses_super_property(), scope->calls_eval());
+ log_->LogFunction(
+ function_scope->start_position(), function_scope->end_position(),
+ *num_parameters, *function_length, *has_duplicate_parameters,
+ *materialized_literal_count, *expected_property_count, language_mode(),
+ function_scope->uses_super_property(), function_scope->calls_eval());
}
return kLazyParsingComplete;
}
@@ -3126,15 +3110,57 @@ Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
Yield::kOnExceptionThrow);
}
+ZoneList<Statement*>* Parser::ParseFunction(
+ const AstRawString* function_name, int pos, FunctionKind kind,
+ FunctionLiteral::FunctionType function_type,
+ DeclarationScope* function_scope, int* num_parameters, int* function_length,
+ bool* has_duplicate_parameters, int* materialized_literal_count,
+ int* expected_property_count, bool* ok) {
+ FunctionState function_state(&function_state_, &scope_state_, function_scope);
+
+ DuplicateFinder duplicate_finder(scanner()->unicode_cache());
+ ExpressionClassifier formals_classifier(this, &duplicate_finder);
+
+ if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state);
+
+ ParserFormalParameters formals(function_scope);
+ ParseFormalParameterList(&formals, CHECK_OK);
+ Expect(Token::RPAREN, CHECK_OK);
+ int formals_end_position = scanner()->location().end_pos;
+ *num_parameters = formals.num_parameters();
+ *function_length = formals.function_length;
+
+ CheckArityRestrictions(formals.arity, kind, formals.has_rest,
+ function_scope->start_position(), formals_end_position,
+ CHECK_OK);
+ Expect(Token::LBRACE, CHECK_OK);
+
+ ZoneList<Statement*>* body = ParseEagerFunctionBody(
+ function_name, pos, formals, kind, function_type, ok);
+
+ // Validate parameter names. We can do this only after parsing the function,
+ // since the function can declare itself strict.
+ const bool allow_duplicate_parameters =
+ is_sloppy(function_scope->language_mode()) && formals.is_simple &&
+ !IsConciseMethod(kind);
+ ValidateFormalParameters(function_scope->language_mode(),
+ allow_duplicate_parameters, CHECK_OK);
+
+ RewriteDestructuringAssignments();
+
+ *has_duplicate_parameters =
+ !classifier()->is_valid_formal_parameter_list_without_duplicates();
+
+ *materialized_literal_count = function_state.materialized_literal_count();
+ *expected_property_count = function_state.expected_property_count();
+ return body;
+}
+
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
const AstRawString* function_name, int pos,
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
- // Everything inside an eagerly parsed function will be parsed eagerly (see
- // comment above). Lazy inner functions are handled separately and they won't
- // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
- // TODO(marja): Refactor parsing modes: remove this.
- ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
+ ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
static const int kFunctionNameAssignmentIndex = 0;
@@ -3286,46 +3312,6 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
return result;
}
-PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
- SingletonLogger* logger, bool is_inner_function, bool may_abort) {
- // This function may be called on a background thread too; record only the
- // main thread preparse times.
- if (pre_parse_timer_ != NULL) {
- pre_parse_timer_->Start();
- }
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
-
- DCHECK_EQ(Token::LBRACE, scanner()->current_token());
-
- if (reusable_preparser_ == NULL) {
- reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
- NULL, stack_limit_);
- reusable_preparser_->set_allow_lazy(true);
-#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
- SET_ALLOW(natives);
- SET_ALLOW(harmony_do_expressions);
- SET_ALLOW(harmony_for_in);
- SET_ALLOW(harmony_function_sent);
- SET_ALLOW(harmony_restrictive_declarations);
- SET_ALLOW(harmony_async_await);
- SET_ALLOW(harmony_trailing_commas);
- SET_ALLOW(harmony_class_fields);
-#undef SET_ALLOW
- }
- // Aborting inner function preparsing would leave scopes in an inconsistent
- // state; we don't parse inner functions in the abortable mode anyway.
- DCHECK(!is_inner_function || !may_abort);
-
- DeclarationScope* function_scope = function_state_->scope();
- PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
- function_scope, parsing_module_, logger, is_inner_function, may_abort,
- use_counts_);
- if (pre_parse_timer_ != NULL) {
- pre_parse_timer_->Stop();
- }
- return result;
-}
-
Expression* Parser::InstallHomeObject(Expression* function_literal,
Expression* home_object) {
Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
@@ -3426,12 +3412,12 @@ FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) {
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
ast_value_factory()->empty_string(), initializer_scope, body,
initializer_state.materialized_literal_count(),
- initializer_state.expected_property_count(), 0,
+ initializer_state.expected_property_count(), 0, count,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression,
- FunctionLiteral::kShouldLazyCompile, initializer_scope->start_position());
+ FunctionLiteral::kShouldLazyCompile, initializer_scope->start_position(),
+ true);
function_literal->set_is_class_field_initializer(true);
- function_literal->scope()->set_arity(count);
return function_literal;
}
@@ -3442,7 +3428,7 @@ FunctionLiteral* Parser::InsertClassFieldInitializer(
constructor->scope(),
constructor->scope()->NewUnresolved(
factory(), ast_value_factory()->this_string(), kNoSourcePosition,
- kNoSourcePosition + 4, THIS_VARIABLE)),
+ THIS_VARIABLE)),
kNoSourcePosition);
constructor->body()->InsertAt(0, call_initializer, zone());
return constructor;
@@ -3636,6 +3622,7 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
}
do_block->set_scope(scope()->FinalizeBlockScope());
do_expr->set_represented_function(class_info->constructor);
+ AddFunctionForNameInference(class_info->constructor);
return do_expr;
}
@@ -3668,10 +3655,8 @@ void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
DCHECK(inner_scope->is_declaration_scope());
Scope* function_scope = inner_scope->outer_scope();
DCHECK(function_scope->is_function_scope());
- ZoneList<Declaration*>* decls = inner_scope->declarations();
BlockState block_state(&scope_state_, inner_scope);
- for (int i = 0; i < decls->length(); ++i) {
- Declaration* decl = decls->at(i);
+ for (Declaration* decl : *inner_scope->declarations()) {
if (decl->proxy()->var()->mode() != VAR || !decl->IsVariableDeclaration()) {
continue;
}
@@ -3781,6 +3766,15 @@ void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
}
isolate->counters()->total_preparse_skipped()->Increment(
total_preparse_skipped_);
+ if (!parsing_on_main_thread_ &&
+ FLAG_runtime_stats ==
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) {
+ // Copy over the counters from the background thread to the main counters on
+ // the isolate.
+ // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
+ // background parsing.
+ isolate->counters()->runtime_call_stats()->Add(runtime_call_stats_);
+ }
}
@@ -3804,18 +3798,12 @@ bool Parser::Parse(ParseInfo* info) {
// Ok to use Isolate here; this function is only called in the main thread.
DCHECK(parsing_on_main_thread_);
Isolate* isolate = info->isolate();
- pre_parse_timer_ = isolate->counters()->pre_parse();
- if (info->is_lazy()) {
- DCHECK(!info->is_eval());
- if (info->shared_info()->is_function()) {
- result = ParseLazy(isolate, info);
- } else {
- result = ParseProgram(isolate, info);
- }
- } else {
+ if (info->is_toplevel()) {
SetCachedData(info);
result = ParseProgram(isolate, info);
+ } else {
+ result = ParseFunction(isolate, info);
}
info->set_literal(result);
@@ -3830,8 +3818,12 @@ void Parser::ParseOnBackground(ParseInfo* info) {
DCHECK(info->literal() == NULL);
FunctionLiteral* result = NULL;
- CompleteParserRecorder recorder;
- if (produce_cached_parse_data()) log_ = &recorder;
+ ParserLogger logger;
+ if (produce_cached_parse_data()) log_ = &logger;
+ if (FLAG_runtime_stats) {
+ // Create separate runtime stats for background parsing.
+ runtime_call_stats_ = new (zone()) RuntimeCallStats();
+ }
std::unique_ptr<Utf16CharacterStream> stream;
Utf16CharacterStream* stream_ptr;
@@ -3854,12 +3846,12 @@ void Parser::ParseOnBackground(ParseInfo* info) {
// don't). We work around this by storing all the scopes which need their end
// position set at the end of the script (the top scope and possible eval
// scopes) and set their end position after we know the script length.
- if (info->is_lazy()) {
- result = DoParseLazy(info, info->function_name(), stream_ptr);
- } else {
+ if (info->is_toplevel()) {
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
scanner_.Initialize(stream_ptr);
result = DoParseProgram(info);
+ } else {
+ result = DoParseFunction(info, info->function_name(), stream_ptr);
}
info->set_literal(result);
@@ -3868,9 +3860,13 @@ void Parser::ParseOnBackground(ParseInfo* info) {
// care of calling Parser::Internalize just before compilation.
if (produce_cached_parse_data()) {
- if (result != NULL) *info->cached_data() = recorder.GetScriptData();
+ if (result != NULL) *info->cached_data() = logger.GetScriptData();
log_ = NULL;
}
+ if (FLAG_runtime_stats) {
+ // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
+ // background parsing.
+ }
}
Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
@@ -3943,9 +3939,9 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
zone());
- // Ensure hash is suitable as a Smi value
+ // Truncate hash to Smi-range.
Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
- args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());
+ args->Add(factory()->NewNumberLiteral(hash_obj->value(), pos), zone());
Expression* call_site = factory()->NewCallRuntime(
Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
@@ -4002,7 +3998,7 @@ ZoneList<Expression*>* Parser::PrepareSpreadArguments(
ZoneList<Expression*>* spread_list =
new (zone()) ZoneList<Expression*>(0, zone());
spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
- args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
+ args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare,
spread_list, kNoSourcePosition),
zone());
return args;
@@ -4338,8 +4334,7 @@ Expression* Parser::RewriteAssignExponentiation(Expression* left,
Expression* result;
DCHECK_NOT_NULL(lhs->raw_name());
- result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position(),
- lhs->end_position());
+ result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position());
args->Add(left, zone());
args->Add(right, zone());
Expression* call =