diff options
author | Michaël Zasso <targos@protonmail.com> | 2020-07-13 10:39:42 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2020-07-13 14:41:41 +0200 |
commit | 12478684aab233942e0d5dc24f195930c8a5e59d (patch) | |
tree | 97dbee955ab91d4df480bcb82274d710a2195e64 /deps/v8/src/parsing | |
parent | 913d36d97da187a3804f6cfa96b4d24a8b7be78a (diff) | |
download | node-new-12478684aab233942e0d5dc24f195930c8a5e59d.tar.gz |
deps: update V8 to 8.4.371.19
PR-URL: https://github.com/nodejs/node/pull/33579
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Shelley Vohr <codebytere@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r-- | deps/v8/src/parsing/expression-scope.h | 37 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.cc | 360 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.h | 434 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser-base.h | 127 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 192 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.h | 35 | ||||
-rw-r--r-- | deps/v8/src/parsing/parsing.cc | 72 | ||||
-rw-r--r-- | deps/v8/src/parsing/pending-compilation-error-handler.cc | 111 | ||||
-rw-r--r-- | deps/v8/src/parsing/pending-compilation-error-handler.h | 54 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data-impl.h | 9 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data.cc | 14 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data.h | 7 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.cc | 9 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.h | 11 | ||||
-rw-r--r-- | deps/v8/src/parsing/rewriter.cc | 19 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner-inl.h | 16 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.cc | 15 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.h | 23 | ||||
-rw-r--r-- | deps/v8/src/parsing/token.h | 10 |
19 files changed, 824 insertions, 731 deletions
diff --git a/deps/v8/src/parsing/expression-scope.h b/deps/v8/src/parsing/expression-scope.h index 6dd55a25c2..9cb04003ab 100644 --- a/deps/v8/src/parsing/expression-scope.h +++ b/deps/v8/src/parsing/expression-scope.h @@ -53,15 +53,36 @@ class ExpressionScope { AsExpressionParsingScope()->TrackVariable(result); } else { Variable* var = Declare(name, pos); - if (IsVarDeclaration() && !parser()->scope()->is_declaration_scope()) { - // Make sure we'll properly resolve the variable since we might be in a - // with or catch scope. In those cases the proxy isn't guaranteed to - // refer to the declared variable, so consider it unresolved. - parser()->scope()->AddUnresolved(result); - } else { - DCHECK_NOT_NULL(var); - result->BindTo(var); + if (IsVarDeclaration()) { + bool passed_through_with = false; + for (Scope* scope = parser()->scope(); !scope->is_declaration_scope(); + scope = scope->outer_scope()) { + if (scope->is_with_scope()) { + passed_through_with = true; + } else if (scope->is_catch_scope()) { + Variable* var = scope->LookupLocal(name); + // If a variable is declared in a catch scope with a masking + // catch-declared variable, the initializing assignment is an + // assignment to the catch-declared variable instead. + // https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks + if (var != nullptr) { + result->set_is_assigned(); + if (passed_through_with) break; + result->BindTo(var); + var->SetMaybeAssigned(); + return result; + } + } + } + if (passed_through_with) { + // If a variable is declared in a with scope, the initializing + // assignment might target a with-declared variable instead. + parser()->scope()->AddUnresolved(result); + return result; + } } + DCHECK_NOT_NULL(var); + result->BindTo(var); } return result; } diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc index 3723636804..37432e05b7 100644 --- a/deps/v8/src/parsing/parse-info.cc +++ b/deps/v8/src/parsing/parse-info.cc @@ -20,64 +20,108 @@ namespace v8 { namespace internal { -ParseInfo::ParseInfo(AccountingAllocator* zone_allocator, int script_id) - : zone_(std::make_unique<Zone>(zone_allocator, ZONE_NAME)), - flags_(0), - extension_(nullptr), - script_scope_(nullptr), - stack_limit_(0), - hash_seed_(0), - function_kind_(FunctionKind::kNormalFunction), - function_syntax_kind_(FunctionSyntaxKind::kDeclaration), +UnoptimizedCompileFlags::UnoptimizedCompileFlags(Isolate* isolate, + int script_id) + : flags_(0), script_id_(script_id), - start_position_(0), - end_position_(0), - parameters_end_pos_(kNoSourcePosition), - function_literal_id_(kFunctionLiteralIdInvalid), - max_function_literal_id_(kFunctionLiteralIdInvalid), - character_stream_(nullptr), - ast_value_factory_(nullptr), - ast_string_constants_(nullptr), - function_name_(nullptr), - runtime_call_stats_(nullptr), - source_range_map_(nullptr), - literal_(nullptr) {} - -ParseInfo::ParseInfo(Isolate* isolate, AccountingAllocator* zone_allocator, - int script_id) - : ParseInfo(zone_allocator, script_id) { - set_hash_seed(HashSeed(isolate)); - set_stack_limit(isolate->stack_guard()->real_climit()); - set_runtime_call_stats(isolate->counters()->runtime_call_stats()); - set_logger(isolate->logger()); - set_ast_string_constants(isolate->ast_string_constants()); - set_collect_source_positions(!FLAG_enable_lazy_source_positions || - isolate->NeedsDetailedOptimizedCodeLineInfo()); - if (!isolate->is_best_effort_code_coverage()) set_coverage_enabled(); - if (isolate->is_block_code_coverage()) set_block_coverage_enabled(); - if (isolate->is_collecting_type_profile()) set_collect_type_profile(); - if (isolate->compiler_dispatcher()->IsEnabled()) { - parallel_tasks_.reset(new ParallelTasks(isolate->compiler_dispatcher())); - } + function_kind_(FunctionKind::kNormalFunction), + function_syntax_kind_(FunctionSyntaxKind::kDeclaration) { + set_collect_type_profile(isolate->is_collecting_type_profile()); + set_coverage_enabled(!isolate->is_best_effort_code_coverage()); + set_block_coverage_enabled(isolate->is_block_code_coverage()); set_might_always_opt(FLAG_always_opt || FLAG_prepare_always_opt); - set_allow_lazy_compile(FLAG_lazy); set_allow_natives_syntax(FLAG_allow_natives_syntax); + set_allow_lazy_compile(FLAG_lazy); set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); set_allow_harmony_import_meta(FLAG_harmony_import_meta); - set_allow_harmony_optional_chaining(FLAG_harmony_optional_chaining); - set_allow_harmony_nullish(FLAG_harmony_nullish); set_allow_harmony_private_methods(FLAG_harmony_private_methods); + set_collect_source_positions(!FLAG_enable_lazy_source_positions || + isolate->NeedsDetailedOptimizedCodeLineInfo()); set_allow_harmony_top_level_await(FLAG_harmony_top_level_await); + set_allow_harmony_logical_assignment(FLAG_harmony_logical_assignment); +} + +// static +UnoptimizedCompileFlags UnoptimizedCompileFlags::ForFunctionCompile( + Isolate* isolate, SharedFunctionInfo shared) { + Script script = Script::cast(shared.script()); + + UnoptimizedCompileFlags flags(isolate, script.id()); + + flags.SetFlagsFromFunction(&shared); + flags.SetFlagsForFunctionFromScript(script); + + flags.set_allow_lazy_parsing(true); + flags.set_is_asm_wasm_broken(shared.is_asm_wasm_broken()); + flags.set_is_repl_mode(shared.is_repl_mode()); + + // CollectTypeProfile uses its own feedback slots. If we have existing + // FeedbackMetadata, we can only collect type profile if the feedback vector + // has the appropriate slots. + flags.set_collect_type_profile( + isolate->is_collecting_type_profile() && + (shared.HasFeedbackMetadata() + ? shared.feedback_metadata().HasTypeProfileSlot() + : script.IsUserJavaScript())); + + // Do not support re-parsing top-level function of a wrapped script. + DCHECK_IMPLIES(flags.is_toplevel(), !script.is_wrapped()); + + return flags; +} + +// static +UnoptimizedCompileFlags UnoptimizedCompileFlags::ForScriptCompile( + Isolate* isolate, Script script) { + UnoptimizedCompileFlags flags(isolate, script.id()); + + flags.SetFlagsForFunctionFromScript(script); + flags.SetFlagsForToplevelCompile( + isolate->is_collecting_type_profile(), script.IsUserJavaScript(), + flags.outer_language_mode(), construct_repl_mode(script.is_repl_mode())); + if (script.is_wrapped()) { + flags.set_function_syntax_kind(FunctionSyntaxKind::kWrapped); + } + + return flags; } -ParseInfo::ParseInfo(Isolate* isolate) - : ParseInfo(isolate, isolate->allocator(), isolate->GetNextScriptId()) { - LOG(isolate, ScriptEvent(Logger::ScriptEventType::kReserveId, script_id())); +// static +UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelCompile( + Isolate* isolate, bool is_user_javascript, LanguageMode language_mode, + REPLMode repl_mode) { + UnoptimizedCompileFlags flags(isolate, isolate->GetNextScriptId()); + flags.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(), + is_user_javascript, language_mode, + repl_mode); + + LOG(isolate, + ScriptEvent(Logger::ScriptEventType::kReserveId, flags.script_id())); + return flags; +} + +// static +UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelFunction( + const UnoptimizedCompileFlags toplevel_flags, + const FunctionLiteral* literal) { + DCHECK(toplevel_flags.is_toplevel()); + DCHECK(!literal->is_toplevel()); + + // Replicate the toplevel flags, then setup the function-specific flags. + UnoptimizedCompileFlags flags = toplevel_flags; + flags.SetFlagsFromFunction(literal); + + return flags; +} + +// static +UnoptimizedCompileFlags UnoptimizedCompileFlags::ForTest(Isolate* isolate) { + return UnoptimizedCompileFlags(isolate, Script::kTemporaryScriptId); } template <typename T> -void ParseInfo::SetFunctionInfo(T function) { - set_language_mode(function->language_mode()); +void UnoptimizedCompileFlags::SetFlagsFromFunction(T function) { + set_outer_language_mode(function->language_mode()); set_function_kind(function->kind()); set_function_syntax_kind(function->syntax_kind()); set_requires_instance_members_initializer( @@ -85,63 +129,88 @@ void ParseInfo::SetFunctionInfo(T function) { set_class_scope_has_private_brand(function->class_scope_has_private_brand()); set_has_static_private_methods_or_accessors( function->has_static_private_methods_or_accessors()); - set_toplevel(function->is_toplevel()); + set_is_toplevel(function->is_toplevel()); set_is_oneshot_iife(function->is_oneshot_iife()); } -ParseInfo::ParseInfo(Isolate* isolate, SharedFunctionInfo shared) - : ParseInfo(isolate, isolate->allocator(), - Script::cast(shared.script()).id()) { - // Do not support re-parsing top-level function of a wrapped script. - // TODO(yangguo): consider whether we need a top-level function in a - // wrapped script at all. - DCHECK_IMPLIES(is_toplevel(), !Script::cast(shared.script()).is_wrapped()); - +void UnoptimizedCompileFlags::SetFlagsForToplevelCompile( + bool is_collecting_type_profile, bool is_user_javascript, + LanguageMode language_mode, REPLMode repl_mode) { set_allow_lazy_parsing(true); - set_asm_wasm_broken(shared.is_asm_wasm_broken()); + set_is_toplevel(true); + set_collect_type_profile(is_user_javascript && is_collecting_type_profile); + set_outer_language_mode( + stricter_language_mode(outer_language_mode(), language_mode)); + set_is_repl_mode((repl_mode == REPLMode::kYes)); - set_start_position(shared.StartPosition()); - set_end_position(shared.EndPosition()); - function_literal_id_ = shared.function_literal_id(); - SetFunctionInfo(&shared); + set_block_coverage_enabled(block_coverage_enabled() && is_user_javascript); +} - Script script = Script::cast(shared.script()); - SetFlagsForFunctionFromScript(script); +void UnoptimizedCompileFlags::SetFlagsForFunctionFromScript(Script script) { + DCHECK_EQ(script_id(), script.id()); - set_repl_mode(shared.is_repl_mode()); + set_is_eval(script.compilation_type() == Script::COMPILATION_TYPE_EVAL); + set_is_module(script.origin_options().IsModule()); + DCHECK(!(is_eval() && is_module())); - // CollectTypeProfile uses its own feedback slots. If we have existing - // FeedbackMetadata, we can only collect type profile if the feedback vector - // has the appropriate slots. - set_collect_type_profile( - isolate->is_collecting_type_profile() && - (shared.HasFeedbackMetadata() - ? shared.feedback_metadata().HasTypeProfileSlot() - : script.IsUserJavaScript())); + set_block_coverage_enabled(block_coverage_enabled() && + script.IsUserJavaScript()); } -ParseInfo::ParseInfo(Isolate* isolate, Script script) - : ParseInfo(isolate, isolate->allocator(), script.id()) { - SetFlagsForToplevelCompileFromScript(isolate, script, - isolate->is_collecting_type_profile()); +UnoptimizedCompileState::UnoptimizedCompileState(Isolate* isolate) + : hash_seed_(HashSeed(isolate)), + allocator_(isolate->allocator()), + ast_string_constants_(isolate->ast_string_constants()), + logger_(isolate->logger()), + parallel_tasks_(isolate->compiler_dispatcher()->IsEnabled() + ? new ParallelTasks(isolate->compiler_dispatcher()) + : nullptr) {} + +UnoptimizedCompileState::UnoptimizedCompileState( + const UnoptimizedCompileState& other) V8_NOEXCEPT + : hash_seed_(other.hash_seed()), + allocator_(other.allocator()), + ast_string_constants_(other.ast_string_constants()), + logger_(other.logger()), + // TODO(leszeks): Should this create a new ParallelTasks instance? + parallel_tasks_(nullptr) {} + +ParseInfo::ParseInfo(const UnoptimizedCompileFlags flags, + UnoptimizedCompileState* state) + : flags_(flags), + state_(state), + zone_(std::make_unique<Zone>(state->allocator(), ZONE_NAME)), + extension_(nullptr), + script_scope_(nullptr), + stack_limit_(0), + parameters_end_pos_(kNoSourcePosition), + max_function_literal_id_(kFunctionLiteralIdInvalid), + character_stream_(nullptr), + ast_value_factory_(nullptr), + function_name_(nullptr), + runtime_call_stats_(nullptr), + source_range_map_(nullptr), + literal_(nullptr), + allow_eval_cache_(false), + contains_asm_module_(false), + language_mode_(flags.outer_language_mode()) { + if (flags.block_coverage_enabled()) { + AllocateSourceRangeMap(); + } +} + +ParseInfo::ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags, + UnoptimizedCompileState* state) + : ParseInfo(flags, state) { + SetPerThreadState(isolate->stack_guard()->real_climit(), + isolate->counters()->runtime_call_stats()); } // static -std::unique_ptr<ParseInfo> ParseInfo::FromParent( - const ParseInfo* outer_parse_info, AccountingAllocator* zone_allocator, +std::unique_ptr<ParseInfo> ParseInfo::ForToplevelFunction( + const UnoptimizedCompileFlags flags, UnoptimizedCompileState* compile_state, const FunctionLiteral* literal, const AstRawString* function_name) { - // Can't use make_unique because the constructor is private. - std::unique_ptr<ParseInfo> result( - new ParseInfo(zone_allocator, outer_parse_info->script_id_)); - - // Replicate shared state of the outer_parse_info. - result->flags_ = outer_parse_info->flags_; - result->set_logger(outer_parse_info->logger()); - result->set_ast_string_constants(outer_parse_info->ast_string_constants()); - result->set_hash_seed(outer_parse_info->hash_seed()); - - DCHECK_EQ(outer_parse_info->parameters_end_pos(), kNoSourcePosition); - DCHECK_NULL(outer_parse_info->extension()); + std::unique_ptr<ParseInfo> result(new ParseInfo(flags, compile_state)); // Clone the function_name AstRawString into the ParseInfo's own // AstValueFactory. @@ -152,10 +221,6 @@ std::unique_ptr<ParseInfo> ParseInfo::FromParent( // Setup function specific details. DCHECK(!literal->is_toplevel()); result->set_function_name(cloned_function_name); - result->set_start_position(literal->start_position()); - result->set_end_position(literal->end_position()); - result->set_function_literal_id(literal->function_literal_id()); - result->SetFunctionInfo(literal); return result; } @@ -165,17 +230,15 @@ ParseInfo::~ParseInfo() = default; DeclarationScope* ParseInfo::scope() const { return literal()->scope(); } template <typename LocalIsolate> -Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate, - Handle<String> source, - ScriptOriginOptions origin_options, - NativesFlag natives) { +Handle<Script> ParseInfo::CreateScript( + LocalIsolate* isolate, Handle<String> source, + MaybeHandle<FixedArray> maybe_wrapped_arguments, + ScriptOriginOptions origin_options, NativesFlag natives) { // Create a script object describing the script to be compiled. - DCHECK_GE(script_id_, 0); + DCHECK(flags().script_id() >= 0 || + flags().script_id() == Script::kTemporaryScriptId); Handle<Script> script = - isolate->factory()->NewScriptWithId(source, script_id_); - if (isolate->NeedsSourcePositionsForProfiling()) { - Script::InitLineEnds(isolate, script); - } + isolate->factory()->NewScriptWithId(source, flags().script_id()); switch (natives) { case EXTENSION_CODE: script->set_type(Script::TYPE_EXTENSION); @@ -187,8 +250,12 @@ Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate, break; } script->set_origin_options(origin_options); - script->set_is_repl_mode(is_repl_mode()); - if (is_eval() && !is_wrapped_as_function()) { + script->set_is_repl_mode(flags().is_repl_mode()); + + DCHECK_EQ(is_wrapped_as_function(), !maybe_wrapped_arguments.is_null()); + if (is_wrapped_as_function()) { + script->set_wrapped_arguments(*maybe_wrapped_arguments.ToHandleChecked()); + } else if (flags().is_eval()) { script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); } @@ -198,15 +265,15 @@ Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate, } template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) - Handle<Script> ParseInfo::CreateScript(Isolate* isolate, - Handle<String> source, - ScriptOriginOptions origin_options, - NativesFlag natives); + Handle<Script> ParseInfo::CreateScript( + Isolate* isolate, Handle<String> source, + MaybeHandle<FixedArray> maybe_wrapped_arguments, + ScriptOriginOptions origin_options, NativesFlag natives); template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) - Handle<Script> ParseInfo::CreateScript(OffThreadIsolate* isolate, - Handle<String> source, - ScriptOriginOptions origin_options, - NativesFlag natives); + Handle<Script> ParseInfo::CreateScript( + OffThreadIsolate* isolate, Handle<String> source, + MaybeHandle<FixedArray> maybe_wrapped_arguments, + ScriptOriginOptions origin_options, NativesFlag natives); AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { if (!ast_value_factory_.get()) { @@ -217,7 +284,7 @@ AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { } void ParseInfo::AllocateSourceRangeMap() { - DCHECK(block_coverage_enabled()); + DCHECK(flags().block_coverage_enabled()); DCHECK_NULL(source_range_map()); set_source_range_map(new (zone()) SourceRangeMap(zone())); } @@ -230,75 +297,34 @@ void ParseInfo::set_character_stream( character_stream_.swap(character_stream); } -void ParseInfo::SetFlagsForToplevelCompile(bool is_collecting_type_profile, - bool is_user_javascript, - LanguageMode language_mode, - REPLMode repl_mode) { - set_allow_lazy_parsing(); - set_toplevel(); - set_collect_type_profile(is_user_javascript && is_collecting_type_profile); - set_language_mode( - stricter_language_mode(this->language_mode(), language_mode)); - set_repl_mode(repl_mode == REPLMode::kYes); - - if (V8_UNLIKELY(is_user_javascript && block_coverage_enabled())) { - AllocateSourceRangeMap(); - } -} - -template <typename LocalIsolate> -void ParseInfo::SetFlagsForToplevelCompileFromScript( - LocalIsolate* isolate, Script script, bool is_collecting_type_profile) { - SetFlagsForFunctionFromScript(script); - SetFlagsForToplevelCompile(is_collecting_type_profile, - script.IsUserJavaScript(), language_mode(), - construct_repl_mode(script.is_repl_mode())); - - if (script.is_wrapped()) { - set_function_syntax_kind(FunctionSyntaxKind::kWrapped); - } -} - void ParseInfo::CheckFlagsForToplevelCompileFromScript( Script script, bool is_collecting_type_profile) { CheckFlagsForFunctionFromScript(script); - DCHECK(allow_lazy_parsing()); - DCHECK(is_toplevel()); - DCHECK_EQ(collect_type_profile(), + DCHECK(flags().allow_lazy_parsing()); + DCHECK(flags().is_toplevel()); + DCHECK_EQ(flags().collect_type_profile(), is_collecting_type_profile && script.IsUserJavaScript()); - DCHECK_EQ(is_repl_mode(), script.is_repl_mode()); + DCHECK_EQ(flags().is_repl_mode(), script.is_repl_mode()); if (script.is_wrapped()) { - DCHECK_EQ(function_syntax_kind(), FunctionSyntaxKind::kWrapped); - } -} - -void ParseInfo::SetFlagsForFunctionFromScript(Script script) { - DCHECK_EQ(script_id_, script.id()); - - set_eval(script.compilation_type() == Script::COMPILATION_TYPE_EVAL); - set_module(script.origin_options().IsModule()); - DCHECK(!(is_eval() && is_module())); - - if (block_coverage_enabled() && script.IsUserJavaScript()) { - AllocateSourceRangeMap(); + DCHECK_EQ(flags().function_syntax_kind(), FunctionSyntaxKind::kWrapped); } } void ParseInfo::CheckFlagsForFunctionFromScript(Script script) { - DCHECK_EQ(script_id_, script.id()); - // We set "is_eval" for wrapped functions to get an outer declaration scope. + DCHECK_EQ(flags().script_id(), script.id()); + // We set "is_eval" for wrapped scripts to get an outer declaration scope. // This is a bit hacky, but ok since we can't be both eval and wrapped. - DCHECK_EQ(is_eval() && !is_wrapped_as_function(), + DCHECK_EQ(flags().is_eval() && !script.is_wrapped(), script.compilation_type() == Script::COMPILATION_TYPE_EVAL); - DCHECK_EQ(is_module(), script.origin_options().IsModule()); - DCHECK_IMPLIES(block_coverage_enabled() && script.IsUserJavaScript(), + DCHECK_EQ(flags().is_module(), script.origin_options().IsModule()); + DCHECK_IMPLIES(flags().block_coverage_enabled() && script.IsUserJavaScript(), source_range_map() != nullptr); } -void ParseInfo::ParallelTasks::Enqueue(ParseInfo* outer_parse_info, - const AstRawString* function_name, - FunctionLiteral* literal) { +void UnoptimizedCompileState::ParallelTasks::Enqueue( + ParseInfo* outer_parse_info, const AstRawString* function_name, + FunctionLiteral* literal) { base::Optional<CompilerDispatcher::JobId> job_id = dispatcher_->Enqueue(outer_parse_info, function_name, literal); if (job_id) { diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h index 4430424eb9..c774f0ae94 100644 --- a/deps/v8/src/parsing/parse-info.h +++ b/deps/v8/src/parsing/parse-info.h @@ -10,7 +10,9 @@ #include <vector> #include "include/v8.h" +#include "src/base/bit-field.h" #include "src/base/export-template.h" +#include "src/base/logging.h" #include "src/common/globals.h" #include "src/handles/handles.h" #include "src/objects/function-kind.h" @@ -38,24 +40,187 @@ class SourceRangeMap; class Utf16CharacterStream; class Zone; +// The flags for a parse + unoptimized compile operation. +#define FLAG_FIELDS(V, _) \ + V(is_toplevel, bool, 1, _) \ + V(is_eager, bool, 1, _) \ + V(is_eval, bool, 1, _) \ + V(outer_language_mode, LanguageMode, 1, _) \ + V(parse_restriction, ParseRestriction, 1, _) \ + V(is_module, bool, 1, _) \ + V(allow_lazy_parsing, bool, 1, _) \ + V(is_lazy_compile, bool, 1, _) \ + V(collect_type_profile, bool, 1, _) \ + V(coverage_enabled, bool, 1, _) \ + V(block_coverage_enabled, bool, 1, _) \ + V(is_asm_wasm_broken, bool, 1, _) \ + V(class_scope_has_private_brand, bool, 1, _) \ + V(requires_instance_members_initializer, bool, 1, _) \ + V(has_static_private_methods_or_accessors, bool, 1, _) \ + V(might_always_opt, bool, 1, _) \ + V(allow_natives_syntax, bool, 1, _) \ + V(allow_lazy_compile, bool, 1, _) \ + V(allow_harmony_dynamic_import, bool, 1, _) \ + V(allow_harmony_import_meta, bool, 1, _) \ + V(allow_harmony_private_methods, bool, 1, _) \ + V(is_oneshot_iife, bool, 1, _) \ + V(collect_source_positions, bool, 1, _) \ + V(allow_harmony_top_level_await, bool, 1, _) \ + V(is_repl_mode, bool, 1, _) \ + V(allow_harmony_logical_assignment, bool, 1, _) + +class V8_EXPORT_PRIVATE UnoptimizedCompileFlags { + public: + // Set-up flags for a toplevel compilation. + static UnoptimizedCompileFlags ForToplevelCompile(Isolate* isolate, + bool is_user_javascript, + LanguageMode language_mode, + REPLMode repl_mode); + + // Set-up flags for a compiling a particular function (either a lazy compile + // or a recompile). + static UnoptimizedCompileFlags ForFunctionCompile(Isolate* isolate, + SharedFunctionInfo shared); + + // Set-up flags for a full compilation of a given script. + static UnoptimizedCompileFlags ForScriptCompile(Isolate* isolate, + Script script); + + // Set-up flags for a parallel toplevel function compilation, based on the + // flags of an existing toplevel compilation. + static UnoptimizedCompileFlags ForToplevelFunction( + const UnoptimizedCompileFlags toplevel_flags, + const FunctionLiteral* literal); + + // Create flags for a test. + static UnoptimizedCompileFlags ForTest(Isolate* isolate); + +#define FLAG_GET_SET(NAME, TYPE, SIZE, _) \ + TYPE NAME() const { return BitFields::NAME::decode(flags_); } \ + UnoptimizedCompileFlags& set_##NAME(TYPE value) { \ + flags_ = BitFields::NAME::update(flags_, value); \ + return *this; \ + } + + FLAG_FIELDS(FLAG_GET_SET, _) + + int script_id() const { return script_id_; } + UnoptimizedCompileFlags& set_script_id(int value) { + script_id_ = value; + return *this; + } + + FunctionKind function_kind() const { return function_kind_; } + UnoptimizedCompileFlags& set_function_kind(FunctionKind value) { + function_kind_ = value; + return *this; + } + + FunctionSyntaxKind function_syntax_kind() const { + return function_syntax_kind_; + } + UnoptimizedCompileFlags& set_function_syntax_kind(FunctionSyntaxKind value) { + function_syntax_kind_ = value; + return *this; + } + + private: + struct BitFields { + DEFINE_BIT_FIELDS(FLAG_FIELDS) + }; + + UnoptimizedCompileFlags(Isolate* isolate, int script_id); + + // Set function info flags based on those in either FunctionLiteral or + // SharedFunctionInfo |function| + template <typename T> + void SetFlagsFromFunction(T function); + void SetFlagsForToplevelCompile(bool is_collecting_type_profile, + bool is_user_javascript, + LanguageMode language_mode, + REPLMode repl_mode); + void SetFlagsForFunctionFromScript(Script script); + + uint32_t flags_; + int script_id_; + FunctionKind function_kind_; + FunctionSyntaxKind function_syntax_kind_; +}; + +#undef FLAG_FIELDS +class ParseInfo; + +// The mutable state for a parse + unoptimized compile operation. +class V8_EXPORT_PRIVATE UnoptimizedCompileState { + public: + explicit UnoptimizedCompileState(Isolate*); + UnoptimizedCompileState(const UnoptimizedCompileState& other) V8_NOEXCEPT; + + class ParallelTasks { + public: + explicit ParallelTasks(CompilerDispatcher* compiler_dispatcher) + : dispatcher_(compiler_dispatcher) { + DCHECK_NOT_NULL(dispatcher_); + } + + void Enqueue(ParseInfo* outer_parse_info, const AstRawString* function_name, + FunctionLiteral* literal); + + using EnqueuedJobsIterator = + std::forward_list<std::pair<FunctionLiteral*, uintptr_t>>::iterator; + + EnqueuedJobsIterator begin() { return enqueued_jobs_.begin(); } + EnqueuedJobsIterator end() { return enqueued_jobs_.end(); } + + CompilerDispatcher* dispatcher() { return dispatcher_; } + + private: + CompilerDispatcher* dispatcher_; + std::forward_list<std::pair<FunctionLiteral*, uintptr_t>> enqueued_jobs_; + }; + + uint64_t hash_seed() const { return hash_seed_; } + AccountingAllocator* allocator() const { return allocator_; } + const AstStringConstants* ast_string_constants() const { + return ast_string_constants_; + } + Logger* logger() const { return logger_; } + PendingCompilationErrorHandler* pending_error_handler() { + return &pending_error_handler_; + } + const PendingCompilationErrorHandler* pending_error_handler() const { + return &pending_error_handler_; + } + ParallelTasks* parallel_tasks() const { return parallel_tasks_.get(); } + + private: + uint64_t hash_seed_; + AccountingAllocator* allocator_; + const AstStringConstants* ast_string_constants_; + PendingCompilationErrorHandler pending_error_handler_; + Logger* logger_; + std::unique_ptr<ParallelTasks> parallel_tasks_; +}; + // A container for the inputs, configuration options, and outputs of parsing. class V8_EXPORT_PRIVATE ParseInfo { public: - explicit ParseInfo(Isolate*); - ParseInfo(Isolate* isolate, Script script); - ParseInfo(Isolate* isolate, SharedFunctionInfo shared); + ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags, + UnoptimizedCompileState* state); // Creates a new parse info based on parent top-level |outer_parse_info| for // function |literal|. - static std::unique_ptr<ParseInfo> FromParent( - const ParseInfo* outer_parse_info, AccountingAllocator* zone_allocator, - const FunctionLiteral* literal, const AstRawString* function_name); + static std::unique_ptr<ParseInfo> ForToplevelFunction( + const UnoptimizedCompileFlags flags, + UnoptimizedCompileState* compile_state, const FunctionLiteral* literal, + const AstRawString* function_name); ~ParseInfo(); template <typename LocalIsolate> EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<Script> CreateScript(LocalIsolate* isolate, Handle<String> source, + MaybeHandle<FixedArray> maybe_wrapped_arguments, ScriptOriginOptions origin_options, NativesFlag natives = NOT_NATIVES_CODE); @@ -65,70 +230,40 @@ class V8_EXPORT_PRIVATE ParseInfo { Zone* zone() const { return zone_.get(); } -// Convenience accessor methods for flags. -#define FLAG_ACCESSOR(flag, getter, setter) \ - bool getter() const { return GetFlag(flag); } \ - void setter() { SetFlag(flag); } \ - void setter(bool val) { SetFlag(flag, val); } - - FLAG_ACCESSOR(kToplevel, is_toplevel, set_toplevel) - FLAG_ACCESSOR(kEager, is_eager, set_eager) - FLAG_ACCESSOR(kEval, is_eval, set_eval) - FLAG_ACCESSOR(kStrictMode, is_strict_mode, set_strict_mode) - FLAG_ACCESSOR(kModule, is_module, set_module) - FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing) - FLAG_ACCESSOR(kLazyCompile, lazy_compile, set_lazy_compile) - FLAG_ACCESSOR(kCollectTypeProfile, collect_type_profile, - set_collect_type_profile) - FLAG_ACCESSOR(kIsAsmWasmBroken, is_asm_wasm_broken, set_asm_wasm_broken) - FLAG_ACCESSOR(kContainsAsmModule, contains_asm_module, - set_contains_asm_module) - FLAG_ACCESSOR(kCoverageEnabled, coverage_enabled, set_coverage_enabled) - FLAG_ACCESSOR(kBlockCoverageEnabled, block_coverage_enabled, - set_block_coverage_enabled) - FLAG_ACCESSOR(kAllowEvalCache, allow_eval_cache, set_allow_eval_cache) - FLAG_ACCESSOR(kRequiresInstanceMembersInitializer, - requires_instance_members_initializer, - set_requires_instance_members_initializer) - FLAG_ACCESSOR(kClassScopeHasPrivateBrand, class_scope_has_private_brand, - set_class_scope_has_private_brand) - FLAG_ACCESSOR(kHasStaticPrivateMethodsOrAccessors, - has_static_private_methods_or_accessors, - set_has_static_private_methods_or_accessors) - FLAG_ACCESSOR(kMightAlwaysOpt, might_always_opt, set_might_always_opt) - FLAG_ACCESSOR(kAllowNativeSyntax, allow_natives_syntax, - set_allow_natives_syntax) - FLAG_ACCESSOR(kAllowLazyCompile, allow_lazy_compile, set_allow_lazy_compile) - FLAG_ACCESSOR(kAllowNativeSyntax, allow_native_syntax, - set_allow_native_syntax) - FLAG_ACCESSOR(kAllowHarmonyDynamicImport, allow_harmony_dynamic_import, - set_allow_harmony_dynamic_import) - FLAG_ACCESSOR(kAllowHarmonyImportMeta, allow_harmony_import_meta, - set_allow_harmony_import_meta) - FLAG_ACCESSOR(kAllowHarmonyOptionalChaining, allow_harmony_optional_chaining, - set_allow_harmony_optional_chaining) - FLAG_ACCESSOR(kAllowHarmonyPrivateMethods, allow_harmony_private_methods, - set_allow_harmony_private_methods) - FLAG_ACCESSOR(kIsOneshotIIFE, is_oneshot_iife, set_is_oneshot_iife) - FLAG_ACCESSOR(kCollectSourcePositions, collect_source_positions, - set_collect_source_positions) - FLAG_ACCESSOR(kAllowHarmonyNullish, allow_harmony_nullish, - set_allow_harmony_nullish) - FLAG_ACCESSOR(kAllowHarmonyTopLevelAwait, allow_harmony_top_level_await, - set_allow_harmony_top_level_await) - FLAG_ACCESSOR(kREPLMode, is_repl_mode, set_repl_mode) - -#undef FLAG_ACCESSOR - - void set_parse_restriction(ParseRestriction restriction) { - SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION); + const UnoptimizedCompileFlags& flags() const { return flags_; } + + // Getters for state. + uint64_t hash_seed() const { return state_->hash_seed(); } + AccountingAllocator* allocator() const { return state_->allocator(); } + const AstStringConstants* ast_string_constants() const { + return state_->ast_string_constants(); } + Logger* logger() const { return state_->logger(); } + PendingCompilationErrorHandler* pending_error_handler() { + return state_->pending_error_handler(); + } + UnoptimizedCompileState::ParallelTasks* parallel_tasks() const { + return state_->parallel_tasks(); + } + const UnoptimizedCompileState* state() const { return state_; } - ParseRestriction parse_restriction() const { - return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL - : NO_PARSE_RESTRICTION; + // Accessors for per-thread state. + uintptr_t stack_limit() const { return stack_limit_; } + RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; } + void SetPerThreadState(uintptr_t stack_limit, + RuntimeCallStats* runtime_call_stats) { + stack_limit_ = stack_limit; + runtime_call_stats_ = runtime_call_stats; } + // Accessor methods for output flags. + bool allow_eval_cache() const { return allow_eval_cache_; } + void set_allow_eval_cache(bool value) { allow_eval_cache_ = value; } + bool contains_asm_module() const { return contains_asm_module_; } + void set_contains_asm_module(bool value) { contains_asm_module_ = value; } + LanguageMode language_mode() const { return language_mode_; } + void set_language_mode(LanguageMode value) { language_mode_ = value; } + Utf16CharacterStream* character_stream() const { return character_stream_.get(); } @@ -166,44 +301,13 @@ class V8_EXPORT_PRIVATE ParseInfo { DeclarationScope* scope() const; - uintptr_t stack_limit() const { return stack_limit_; } - void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } - - uint64_t hash_seed() const { return hash_seed_; } - void set_hash_seed(uint64_t hash_seed) { hash_seed_ = hash_seed; } - - int start_position() const { return start_position_; } - void set_start_position(int start_position) { - start_position_ = start_position; - } - - int end_position() const { return end_position_; } - void set_end_position(int end_position) { end_position_ = end_position; } - int parameters_end_pos() const { return parameters_end_pos_; } void set_parameters_end_pos(int parameters_end_pos) { parameters_end_pos_ = parameters_end_pos; } - int function_literal_id() const { return function_literal_id_; } - void set_function_literal_id(int function_literal_id) { - function_literal_id_ = function_literal_id; - } - - FunctionKind function_kind() const { return function_kind_; } - void set_function_kind(FunctionKind function_kind) { - function_kind_ = function_kind; - } - - FunctionSyntaxKind function_syntax_kind() const { - return function_syntax_kind_; - } - void set_function_syntax_kind(FunctionSyntaxKind function_syntax_kind) { - function_syntax_kind_ = function_syntax_kind; - } - bool is_wrapped_as_function() const { - return function_syntax_kind() == FunctionSyntaxKind::kWrapped; + return flags().function_syntax_kind() == FunctionSyntaxKind::kWrapped; } int max_function_literal_id() const { return max_function_literal_id_; } @@ -211,163 +315,45 @@ class V8_EXPORT_PRIVATE ParseInfo { max_function_literal_id_ = max_function_literal_id; } - const AstStringConstants* ast_string_constants() const { - return ast_string_constants_; - } - void set_ast_string_constants( - const AstStringConstants* ast_string_constants) { - ast_string_constants_ = ast_string_constants; - } - - RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; } - void set_runtime_call_stats(RuntimeCallStats* runtime_call_stats) { - runtime_call_stats_ = runtime_call_stats; - } - Logger* logger() const { return logger_; } - void set_logger(Logger* logger) { logger_ = logger; } - void AllocateSourceRangeMap(); SourceRangeMap* source_range_map() const { return source_range_map_; } void set_source_range_map(SourceRangeMap* source_range_map) { source_range_map_ = source_range_map; } - PendingCompilationErrorHandler* pending_error_handler() { - return &pending_error_handler_; - } - - class ParallelTasks { - public: - explicit ParallelTasks(CompilerDispatcher* compiler_dispatcher) - : dispatcher_(compiler_dispatcher) { - DCHECK(dispatcher_); - } - - void Enqueue(ParseInfo* outer_parse_info, const AstRawString* function_name, - FunctionLiteral* literal); - - using EnqueuedJobsIterator = - std::forward_list<std::pair<FunctionLiteral*, uintptr_t>>::iterator; - - EnqueuedJobsIterator begin() { return enqueued_jobs_.begin(); } - EnqueuedJobsIterator end() { return enqueued_jobs_.end(); } - - CompilerDispatcher* dispatcher() { return dispatcher_; } - - private: - CompilerDispatcher* dispatcher_; - std::forward_list<std::pair<FunctionLiteral*, uintptr_t>> enqueued_jobs_; - }; - - ParallelTasks* parallel_tasks() { return parallel_tasks_.get(); } - - void SetFlagsForToplevelCompile(bool is_collecting_type_profile, - bool is_user_javascript, - LanguageMode language_mode, - REPLMode repl_mode); - void CheckFlagsForFunctionFromScript(Script script); - int script_id() const { return script_id_; } - //-------------------------------------------------------------------------- - - LanguageMode language_mode() const { - return construct_language_mode(is_strict_mode()); - } - void set_language_mode(LanguageMode language_mode) { - STATIC_ASSERT(LanguageModeSize == 2); - set_strict_mode(is_strict(language_mode)); - } - private: - ParseInfo(AccountingAllocator* zone_allocator, int script_id); - ParseInfo(Isolate*, AccountingAllocator* zone_allocator, int script_id); + ParseInfo(const UnoptimizedCompileFlags flags, + UnoptimizedCompileState* state); - void SetFlagsForFunctionFromScript(Script script); - - template <typename LocalIsolate> - void SetFlagsForToplevelCompileFromScript(LocalIsolate* isolate, - Script script, - bool is_collecting_type_profile); void CheckFlagsForToplevelCompileFromScript(Script script, bool is_collecting_type_profile); - // Set function info flags based on those in either FunctionLiteral or - // SharedFunctionInfo |function| - template <typename T> - void SetFunctionInfo(T function); - - // Various configuration flags for parsing. - enum Flag : uint32_t { - // ---------- Input flags --------------------------- - kToplevel = 1u << 0, - kEager = 1u << 1, - kEval = 1u << 2, - kStrictMode = 1u << 3, - kNative = 1u << 4, - kParseRestriction = 1u << 5, - kModule = 1u << 6, - kAllowLazyParsing = 1u << 7, - kLazyCompile = 1u << 8, - kCollectTypeProfile = 1u << 9, - kCoverageEnabled = 1u << 10, - kBlockCoverageEnabled = 1u << 11, - kIsAsmWasmBroken = 1u << 12, - kAllowEvalCache = 1u << 13, - kRequiresInstanceMembersInitializer = 1u << 14, - kContainsAsmModule = 1u << 15, - kMightAlwaysOpt = 1u << 16, - kAllowLazyCompile = 1u << 17, - kAllowNativeSyntax = 1u << 18, - kAllowHarmonyPublicFields = 1u << 19, - kAllowHarmonyStaticFields = 1u << 20, - kAllowHarmonyDynamicImport = 1u << 21, - kAllowHarmonyImportMeta = 1u << 22, - kAllowHarmonyOptionalChaining = 1u << 23, - kHasStaticPrivateMethodsOrAccessors = 1u << 24, - kAllowHarmonyPrivateMethods = 1u << 25, - kIsOneshotIIFE = 1u << 26, - kCollectSourcePositions = 1u << 27, - kAllowHarmonyNullish = 1u << 28, - kAllowHarmonyTopLevelAwait = 1u << 29, - kREPLMode = 1u << 30, - kClassScopeHasPrivateBrand = 1u << 31, - }; - //------------- Inputs to parsing and scope analysis ----------------------- + const UnoptimizedCompileFlags flags_; + UnoptimizedCompileState* state_; + std::unique_ptr<Zone> zone_; - uint32_t flags_; v8::Extension* extension_; DeclarationScope* script_scope_; uintptr_t stack_limit_; - uint64_t hash_seed_; - FunctionKind function_kind_; - FunctionSyntaxKind function_syntax_kind_; - int script_id_; - int start_position_; - int end_position_; int parameters_end_pos_; - int function_literal_id_; int max_function_literal_id_; //----------- Inputs+Outputs of parsing and scope analysis ----------------- std::unique_ptr<Utf16CharacterStream> character_stream_; std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_; std::unique_ptr<AstValueFactory> ast_value_factory_; - const class AstStringConstants* ast_string_constants_; const AstRawString* function_name_; RuntimeCallStats* runtime_call_stats_; - Logger* logger_; SourceRangeMap* source_range_map_; // Used when block coverage is enabled. - std::unique_ptr<ParallelTasks> parallel_tasks_; //----------- Output of parsing and scope analysis ------------------------ FunctionLiteral* literal_; - PendingCompilationErrorHandler pending_error_handler_; - - void SetFlag(Flag f) { flags_ |= f; } - void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; } - bool GetFlag(Flag f) const { return (flags_ & f) != 0; } + bool allow_eval_cache_ : 1; + bool contains_asm_module_ : 1; + LanguageMode language_mode_ : 1; }; } // namespace internal diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index 29e527ce2c..903ce2bb7f 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -23,6 +23,7 @@ #include "src/objects/function-kind.h" #include "src/parsing/expression-scope.h" #include "src/parsing/func-name-inferrer.h" +#include "src/parsing/parse-info.h" #include "src/parsing/scanner.h" #include "src/parsing/token.h" #include "src/utils/pointer-with-payload.h" @@ -241,7 +242,7 @@ class ParserBase { v8::Extension* extension, AstValueFactory* ast_value_factory, PendingCompilationErrorHandler* pending_error_handler, RuntimeCallStats* runtime_call_stats, Logger* logger, - int script_id, bool parsing_module, bool parsing_on_main_thread) + UnoptimizedCompileFlags flags, bool parsing_on_main_thread) : scope_(nullptr), original_scope_(nullptr), function_state_(nullptr), @@ -252,56 +253,25 @@ class ParserBase { runtime_call_stats_(runtime_call_stats), logger_(logger), parsing_on_main_thread_(parsing_on_main_thread), - parsing_module_(parsing_module), stack_limit_(stack_limit), pending_error_handler_(pending_error_handler), zone_(zone), expression_scope_(nullptr), scanner_(scanner), + flags_(flags), function_literal_id_(0), - script_id_(script_id), - default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), - allow_natives_(false), - allow_harmony_dynamic_import_(false), - allow_harmony_import_meta_(false), - allow_harmony_private_methods_(false), - allow_harmony_top_level_await_(false), - allow_eval_cache_(true) { + default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile) { pointer_buffer_.reserve(32); variable_buffer_.reserve(32); } -#define ALLOW_ACCESSORS(name) \ - bool allow_##name() const { return allow_##name##_; } \ - void set_allow_##name(bool allow) { allow_##name##_ = allow; } + const UnoptimizedCompileFlags& flags() const { return flags_; } - ALLOW_ACCESSORS(natives) - ALLOW_ACCESSORS(harmony_dynamic_import) - ALLOW_ACCESSORS(harmony_import_meta) - ALLOW_ACCESSORS(harmony_private_methods) - ALLOW_ACCESSORS(harmony_top_level_await) - ALLOW_ACCESSORS(eval_cache) - -#undef ALLOW_ACCESSORS + bool allow_eval_cache() const { return allow_eval_cache_; } + void set_allow_eval_cache(bool allow) { allow_eval_cache_ = allow; } V8_INLINE bool has_error() const { return scanner()->has_parser_error(); } - bool allow_harmony_optional_chaining() const { - return scanner()->allow_harmony_optional_chaining(); - } - - void set_allow_harmony_optional_chaining(bool allow) { - scanner()->set_allow_harmony_optional_chaining(allow); - } - - bool allow_harmony_nullish() const { - return scanner()->allow_harmony_nullish(); - } - - void set_allow_harmony_nullish(bool allow) { - scanner()->set_allow_harmony_nullish(allow); - } - uintptr_t stack_limit() const { return stack_limit_; } void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } @@ -885,8 +855,6 @@ class ParserBase { // Any further calls to Next or peek will return the illegal token. if (GetCurrentStackPosition() < stack_limit_) set_stack_overflow(); } - int script_id() { return script_id_; } - void set_script_id(int id) { script_id_ = id; } V8_INLINE Token::Value peek() { return scanner()->peek(); } @@ -1077,7 +1045,7 @@ class ParserBase { return IsResumableFunction(function_state_->kind()); } bool is_await_allowed() const { - return is_async_function() || (allow_harmony_top_level_await() && + return is_async_function() || (flags().allow_harmony_top_level_await() && IsModule(function_state_->kind())); } const PendingCompilationErrorHandler* pending_error_handler() const { @@ -1279,7 +1247,12 @@ class ParserBase { // hoisted over such a scope. void CheckConflictingVarDeclarations(DeclarationScope* scope) { if (has_error()) return; - Declaration* decl = scope->CheckConflictingVarDeclarations(); + bool allowed_catch_binding_var_redeclaration = false; + Declaration* decl = scope->CheckConflictingVarDeclarations( + &allowed_catch_binding_var_redeclaration); + if (allowed_catch_binding_var_redeclaration) { + impl()->CountUsage(v8::Isolate::kVarRedeclaredCatchBinding); + } if (decl != nullptr) { // In ES6, conflicting variable bindings are early errors. const AstRawString* name = decl->var()->raw_name(); @@ -1501,16 +1474,14 @@ class ParserBase { FormalParametersT* parent_parameters_; }; - class FunctionBodyParsingScope { + class FunctionParsingScope { public: - explicit FunctionBodyParsingScope(Impl* parser) + explicit FunctionParsingScope(Impl* parser) : parser_(parser), expression_scope_(parser_->expression_scope_) { parser_->expression_scope_ = nullptr; } - ~FunctionBodyParsingScope() { - parser_->expression_scope_ = expression_scope_; - } + ~FunctionParsingScope() { parser_->expression_scope_ = expression_scope_; } private: Impl* parser_; @@ -1534,7 +1505,6 @@ class ParserBase { RuntimeCallStats* runtime_call_stats_; internal::Logger* logger_; bool parsing_on_main_thread_; - const bool parsing_module_; uintptr_t stack_limit_; PendingCompilationErrorHandler* pending_error_handler_; @@ -1549,8 +1519,8 @@ class ParserBase { Scanner* scanner_; + const UnoptimizedCompileFlags flags_; int function_literal_id_; - int script_id_; FunctionLiteral::EagerCompileHint default_eager_compile_hint_; @@ -1589,12 +1559,7 @@ class ParserBase { bool accept_IN_ = true; - bool allow_natives_; - bool allow_harmony_dynamic_import_; - bool allow_harmony_import_meta_; - bool allow_harmony_private_methods_; - bool allow_harmony_top_level_await_; - bool allow_eval_cache_; + bool allow_eval_cache_ = true; }; template <typename Impl> @@ -1644,7 +1609,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) { } if (!Token::IsValidIdentifier(next, language_mode(), is_generator(), - parsing_module_ || is_async_function())) { + flags().is_module() || is_async_function())) { ReportUnexpectedToken(next); return impl()->EmptyIdentifierString(); } @@ -1668,7 +1633,7 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier( if (!Token::IsValidIdentifier( next, language_mode(), IsGeneratorFunction(function_kind), - parsing_module_ || IsAsyncFunction(function_kind))) { + flags().is_module() || IsAsyncFunction(function_kind))) { ReportUnexpectedToken(next); return impl()->EmptyIdentifierString(); } @@ -1879,7 +1844,7 @@ ParserBase<Impl>::ParsePrimaryExpression() { return ParseSuperExpression(is_new); } case Token::IMPORT: - if (!allow_harmony_dynamic_import()) break; + if (!flags().allow_harmony_dynamic_import()) break; return ParseImportExpressions(); case Token::LBRACK: @@ -1942,7 +1907,7 @@ ParserBase<Impl>::ParsePrimaryExpression() { return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false); case Token::MOD: - if (allow_natives() || extension_ != nullptr) { + if (flags().allow_natives_syntax() || extension_ != nullptr) { return ParseV8Intrinsic(); } break; @@ -2188,7 +2153,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty( prop_info->kind = ParsePropertyKind::kNotSet; return impl()->FailureExpression(); } - if (V8_UNLIKELY(!allow_harmony_private_methods() && + if (V8_UNLIKELY(!flags().allow_harmony_private_methods() && (IsAccessor(prop_info->kind) || prop_info->kind == ParsePropertyKind::kMethod))) { ReportUnexpectedToken(Next()); @@ -2437,7 +2402,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info, template <typename Impl> typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberInitializer( ClassInfo* class_info, int beg_pos, bool is_static) { - FunctionBodyParsingScope body_parsing_scope(impl()); + FunctionParsingScope body_parsing_scope(impl()); DeclarationScope* initializer_scope = is_static ? class_info->static_fields_scope : class_info->instance_members_scope; @@ -2535,8 +2500,9 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info, // IdentifierReference Initializer? DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal); - if (!Token::IsValidIdentifier(name_token, language_mode(), is_generator(), - parsing_module_ || is_async_function())) { + if (!Token::IsValidIdentifier( + name_token, language_mode(), is_generator(), + flags().is_module() || is_async_function())) { ReportUnexpectedToken(Next()); return impl()->NullLiteralProperty(); } @@ -2789,6 +2755,11 @@ ParserBase<Impl>::ParseAssignmentExpressionCoverGrammar() { Token::Value op = peek(); if (!Token::IsArrowOrAssignmentOp(op)) return expression; + if ((op == Token::ASSIGN_NULLISH || op == Token::ASSIGN_OR || + op == Token::ASSIGN_AND) && + !flags().allow_harmony_logical_assignment()) { + return expression; + } // Arrow functions. if (V8_UNLIKELY(op == Token::ARROW)) { @@ -3399,13 +3370,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { if (is_optional) { DCHECK_EQ(scanner()->current_token(), Token::QUESTION_PERIOD); int pos = position(); - Token::Value next = Next(); - if (V8_UNLIKELY(!Token::IsPropertyName(next))) { - ReportUnexpectedToken(next); - return impl()->FailureExpression(); - } - IdentifierT name = impl()->GetSymbol(); - ExpressionT key = factory()->NewStringLiteral(name, position()); + ExpressionT key = ParsePropertyOrPrivatePropertyName(); result = factory()->NewProperty(result, key, pos, is_optional); break; } @@ -3456,8 +3421,10 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() { if (peek() == Token::SUPER) { const bool is_new = true; result = ParseSuperExpression(is_new); - } else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT && - (!allow_harmony_import_meta() || PeekAhead() == Token::LPAREN)) { + } else if (flags().allow_harmony_dynamic_import() && + peek() == Token::IMPORT && + (!flags().allow_harmony_import_meta() || + PeekAhead() == Token::LPAREN)) { impl()->ReportMessageAt(scanner()->peek_location(), MessageTemplate::kImportCallNotNewExpression); return impl()->FailureExpression(); @@ -3555,14 +3522,14 @@ ParserBase<Impl>::ParseMemberExpression() { template <typename Impl> typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseImportExpressions() { - DCHECK(allow_harmony_dynamic_import()); + DCHECK(flags().allow_harmony_dynamic_import()); Consume(Token::IMPORT); int pos = position(); - if (allow_harmony_import_meta() && Check(Token::PERIOD)) { + if (flags().allow_harmony_import_meta() && Check(Token::PERIOD)) { ExpectContextualKeyword(ast_value_factory()->meta_string(), "import.meta", pos); - if (!parsing_module_) { + if (!flags().is_module()) { impl()->ReportMessageAt(scanner()->location(), MessageTemplate::kImportMetaOutsideModule); return impl()->FailureExpression(); @@ -3572,7 +3539,7 @@ ParserBase<Impl>::ParseImportExpressions() { } if (V8_UNLIKELY(peek() != Token::LPAREN)) { - if (!parsing_module_) { + if (!flags().is_module()) { impl()->ReportMessageAt(scanner()->location(), MessageTemplate::kImportOutsideModule); } else { @@ -4157,8 +4124,6 @@ void ParserBase<Impl>::ParseFunctionBody( StatementListT* body, IdentifierT function_name, int pos, const FormalParametersT& parameters, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, FunctionBodyType body_type) { - FunctionBodyParsingScope body_parsing_scope(impl()); - if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables(); DeclarationScope* function_scope = parameters.scope; @@ -4435,6 +4400,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( Consume(Token::LBRACE); AcceptINScope scope(this, true); + FunctionParsingScope body_parsing_scope(impl()); ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition, parameters, kind, FunctionSyntaxKind::kAnonymousExpression, @@ -4445,6 +4411,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( } else { Consume(Token::LBRACE); AcceptINScope scope(this, true); + FunctionParsingScope body_parsing_scope(impl()); ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition, formal_parameters, kind, FunctionSyntaxKind::kAnonymousExpression, @@ -4454,6 +4421,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( } else { // Single-expression body has_braces = false; + FunctionParsingScope body_parsing_scope(impl()); ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition, formal_parameters, kind, FunctionSyntaxKind::kAnonymousExpression, @@ -4493,8 +4461,9 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( const char* event_name = is_lazy_top_level_function ? "preparse-no-resolution" : "parse"; const char* name = "arrow function"; - logger_->FunctionEvent(event_name, script_id(), ms, scope->start_position(), - scope->end_position(), name, strlen(name)); + logger_->FunctionEvent(event_name, flags().script_id(), ms, + scope->start_position(), scope->end_position(), name, + strlen(name)); } return function_literal; diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 2a1ad0e98b..63b8b9c6f9 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -15,6 +15,7 @@ #include "src/base/overflowing-math.h" #include "src/base/platform/platform.h" #include "src/codegen/bailout-reason.h" +#include "src/common/globals.h" #include "src/common/message-template.h" #include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/logging/counters.h" @@ -416,13 +417,12 @@ Expression* Parser::NewV8RuntimeFunctionForFuzzing( } Parser::Parser(ParseInfo* info) - : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), - info->extension(), info->GetOrCreateAstValueFactory(), - info->pending_error_handler(), - info->runtime_call_stats(), info->logger(), - info->script_id(), info->is_module(), true), + : ParserBase<Parser>( + info->zone(), &scanner_, info->stack_limit(), info->extension(), + info->GetOrCreateAstValueFactory(), info->pending_error_handler(), + info->runtime_call_stats(), info->logger(), info->flags(), true), info_(info), - scanner_(info->character_stream(), info->is_module()), + scanner_(info->character_stream(), flags()), preparser_zone_(info->zone()->allocator(), ZONE_NAME), reusable_preparser_(nullptr), mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. @@ -445,20 +445,13 @@ Parser::Parser(ParseInfo* info) // of functions without an outer context when setting a breakpoint through // Debug::FindSharedFunctionInfoInScript // We also compile eagerly for kProduceExhaustiveCodeCache. - bool can_compile_lazily = info->allow_lazy_compile() && !info->is_eager(); + bool can_compile_lazily = flags().allow_lazy_compile() && !flags().is_eager(); set_default_eager_compile_hint(can_compile_lazily ? FunctionLiteral::kShouldLazyCompile : FunctionLiteral::kShouldEagerCompile); - allow_lazy_ = info->allow_lazy_compile() && info->allow_lazy_parsing() && + allow_lazy_ = flags().allow_lazy_compile() && flags().allow_lazy_parsing() && info->extension() == nullptr && can_compile_lazily; - set_allow_natives(info->allow_natives_syntax()); - set_allow_harmony_dynamic_import(info->allow_harmony_dynamic_import()); - set_allow_harmony_import_meta(info->allow_harmony_import_meta()); - set_allow_harmony_nullish(info->allow_harmony_nullish()); - set_allow_harmony_optional_chaining(info->allow_harmony_optional_chaining()); - set_allow_harmony_private_methods(info->allow_harmony_private_methods()); - set_allow_harmony_top_level_await(info->allow_harmony_top_level_await()); for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { use_counts_[feature] = 0; @@ -469,7 +462,7 @@ void Parser::InitializeEmptyScopeChain(ParseInfo* info) { DCHECK_NULL(original_scope_); DCHECK_NULL(info->script_scope()); DeclarationScope* script_scope = - NewScriptScope(info->is_repl_mode() ? REPLMode::kYes : REPLMode::kNo); + NewScriptScope(flags().is_repl_mode() ? REPLMode::kYes : REPLMode::kNo); info->set_script_scope(script_scope); original_scope_ = script_scope; } @@ -485,7 +478,7 @@ void Parser::DeserializeScopeChain( original_scope_ = Scope::DeserializeScopeChain( isolate, zone(), *outer_scope_info, info->script_scope(), ast_value_factory(), mode); - if (info->is_eval() || IsArrowFunction(info->function_kind())) { + if (flags().is_eval() || IsArrowFunction(flags().function_kind())) { original_scope_->GetReceiverScope()->DeserializeReceiver( ast_value_factory()); } @@ -515,18 +508,18 @@ void MaybeProcessSourceRanges(ParseInfo* parse_info, Expression* root, } // namespace -FunctionLiteral* Parser::ParseProgram( - Isolate* isolate, Handle<Script> script, ParseInfo* info, - MaybeHandle<ScopeInfo> maybe_outer_scope_info) { +void Parser::ParseProgram(Isolate* isolate, Handle<Script> script, + ParseInfo* info, + MaybeHandle<ScopeInfo> maybe_outer_scope_info) { // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, // see comment for HistogramTimerScope class. - DCHECK_EQ(script->id(), script_id()); + DCHECK_EQ(script->id(), flags().script_id()); // 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( - runtime_call_stats_, info->is_eval() + runtime_call_stats_, flags().is_eval() ? RuntimeCallCounterId::kParseEval : RuntimeCallCounterId::kParseProgram); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); @@ -546,6 +539,7 @@ FunctionLiteral* Parser::ParseProgram( FunctionLiteral* result = DoParseProgram(isolate, info); MaybeResetCharacterStream(info, result); MaybeProcessSourceRanges(info, result, stack_limit_); + PostProcessParseResult(isolate, info, result); HandleSourceURLComments(isolate, script); @@ -554,14 +548,14 @@ FunctionLiteral* Parser::ParseProgram( const char* event_name = "parse-eval"; int start = -1; int end = -1; - if (!info->is_eval()) { + if (!flags().is_eval()) { event_name = "parse-script"; start = 0; end = String::cast(script->source()).length(); } - LOG(isolate, FunctionEvent(event_name, script_id(), ms, start, end, "", 0)); + LOG(isolate, + FunctionEvent(event_name, flags().script_id(), ms, start, end, "", 0)); } - return result; } FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { @@ -574,16 +568,14 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); ResetFunctionLiteralId(); - DCHECK(info->function_literal_id() == kFunctionLiteralIdTopLevel || - info->function_literal_id() == kFunctionLiteralIdInvalid); FunctionLiteral* result = nullptr; { Scope* outer = original_scope_; DCHECK_NOT_NULL(outer); - if (info->is_eval()) { + if (flags().is_eval()) { outer = NewEvalScope(outer); - } else if (parsing_module_) { + } else if (flags().is_module()) { DCHECK_EQ(outer, info->script_scope()); outer = NewModuleScope(info->script_scope()); } @@ -594,15 +586,15 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { FunctionState function_state(&function_state_, &scope_, scope); ScopedPtrList<Statement> body(pointer_buffer()); int beg_pos = scanner()->location().beg_pos; - if (parsing_module_) { - DCHECK(info->is_module()); + if (flags().is_module()) { + DCHECK(flags().is_module()); PrepareGeneratorVariables(); Expression* initial_yield = BuildInitialYield(kNoSourcePosition, kGeneratorFunction); body.Add( factory()->NewExpressionStatement(initial_yield, kNoSourcePosition)); - if (allow_harmony_top_level_await()) { + if (flags().allow_harmony_top_level_await()) { // First parse statements into a buffer. Then, if there was a // top level await, create an inner block and rewrite the body of the // module as an async function. Otherwise merge the statements back @@ -636,7 +628,7 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { } else if (info->is_wrapped_as_function()) { DCHECK(parsing_on_main_thread_); ParseWrapped(isolate, info, &body, scope, zone()); - } else if (info->is_repl_mode()) { + } else if (flags().is_repl_mode()) { ParseREPLProgram(info, &body, scope); } else { // Don't count the mode in the use counters--give the program a chance @@ -661,13 +653,13 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { } // Internalize the ast strings in the case of eval so we can check for // conflicting var declarations with outer scope-info-backed scopes. - if (info->is_eval()) { + if (flags().is_eval()) { DCHECK(parsing_on_main_thread_); info->ast_value_factory()->Internalize(isolate); } CheckConflictingVarDeclarations(scope); - if (info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { + if (flags().parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { if (body.length() != 1 || !body.at(0)->IsExpressionStatement() || !body.at(0) ->AsExpressionStatement() @@ -692,6 +684,33 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) { return result; } +void Parser::PostProcessParseResult(Isolate* isolate, ParseInfo* info, + FunctionLiteral* literal) { + if (literal == nullptr) return; + + info->set_literal(literal); + info->set_language_mode(literal->language_mode()); + if (info->flags().is_eval()) { + info->set_allow_eval_cache(allow_eval_cache()); + } + + // We cannot internalize on a background thread; a foreground task will take + // care of calling AstValueFactory::Internalize just before compilation. + DCHECK_EQ(isolate != nullptr, parsing_on_main_thread_); + if (isolate) info->ast_value_factory()->Internalize(isolate); + + { + RuntimeCallTimerScope runtimeTimer(info->runtime_call_stats(), + RuntimeCallCounterId::kCompileAnalyse, + RuntimeCallStats::kThreadSpecific); + if (!Rewriter::Rewrite(info) || !DeclarationScope::Analyze(info)) { + // Null out the literal to indicate that something failed. + info->set_literal(nullptr); + return; + } + } +} + ZonePtrList<const AstRawString>* Parser::PrepareWrappedArguments( Isolate* isolate, ParseInfo* info, Zone* zone) { DCHECK(parsing_on_main_thread_); @@ -745,7 +764,7 @@ void Parser::ParseREPLProgram(ParseInfo* info, ScopedPtrList<Statement>* body, // completion value of the script is obtained by manually invoking // the {Rewriter} which will return a VariableProxy referencing the // result. - DCHECK(info->is_repl_mode()); + DCHECK(flags().is_repl_mode()); this->scope()->SetLanguageMode(info->language_mode()); PrepareGeneratorVariables(); @@ -791,8 +810,8 @@ Expression* Parser::WrapREPLResult(Expression* value) { false); } -FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, - Handle<SharedFunctionInfo> shared_info) { +void Parser::ParseFunction(Isolate* isolate, ParseInfo* info, + Handle<SharedFunctionInfo> shared_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_); @@ -815,6 +834,10 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, Script::cast(shared_info->script()).wrapped_arguments(), isolate); } + int start_position = shared_info->StartPosition(); + int end_position = shared_info->EndPosition(); + int function_literal_id = shared_info->function_literal_id(); + // Initialize parser state. Handle<String> name(shared_info->Name(), isolate); info->set_function_name(ast_value_factory()->GetString(name)); @@ -827,9 +850,11 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, // function is in heritage position. Otherwise the function scope's skip bit // will be correctly inherited from the outer scope. ClassScope::HeritageParsingScope heritage(original_scope_->AsClassScope()); - result = DoParseFunction(isolate, info, info->function_name()); + result = DoParseFunction(isolate, info, start_position, end_position, + function_literal_id, info->function_name()); } else { - result = DoParseFunction(isolate, info, info->function_name()); + result = DoParseFunction(isolate, info, start_position, end_position, + function_literal_id, info->function_name()); } MaybeResetCharacterStream(info, result); MaybeProcessSourceRanges(info, result, stack_limit_); @@ -837,23 +862,25 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, Handle<String> inferred_name(shared_info->inferred_name(), isolate); result->set_inferred_name(inferred_name); } + PostProcessParseResult(isolate, info, result); if (V8_UNLIKELY(FLAG_log_function_events) && result != nullptr) { double ms = timer.Elapsed().InMillisecondsF(); - // We need to make sure that the debug-name is available. - ast_value_factory()->Internalize(isolate); + // We should already be internalized by now, so the debug name will be + // available. DeclarationScope* function_scope = result->scope(); std::unique_ptr<char[]> function_name = result->GetDebugName(); LOG(isolate, - FunctionEvent("parse-function", script_id(), ms, + FunctionEvent("parse-function", flags().script_id(), ms, function_scope->start_position(), function_scope->end_position(), function_name.get(), strlen(function_name.get()))); } - return result; } FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, + int start_position, int end_position, + int function_literal_id, const AstRawString* raw_name) { DCHECK_EQ(parsing_on_main_thread_, isolate != nullptr); DCHECK_NOT_NULL(raw_name); @@ -863,8 +890,8 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, fni_.PushEnclosingName(raw_name); ResetFunctionLiteralId(); - DCHECK_LT(0, info->function_literal_id()); - SkipFunctionLiterals(info->function_literal_id() - 1); + DCHECK_LT(0, function_literal_id); + SkipFunctionLiterals(function_literal_id - 1); ParsingModeScope parsing_mode(this, PARSE_EAGERLY); @@ -880,10 +907,10 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, BlockState block_state(&scope_, outer); DCHECK(is_sloppy(outer->language_mode()) || is_strict(info->language_mode())); - FunctionKind kind = info->function_kind(); - DCHECK_IMPLIES( - IsConciseMethod(kind) || IsAccessorFunction(kind), - info->function_syntax_kind() == FunctionSyntaxKind::kAccessorOrMethod); + FunctionKind kind = flags().function_kind(); + DCHECK_IMPLIES(IsConciseMethod(kind) || IsAccessorFunction(kind), + flags().function_syntax_kind() == + FunctionSyntaxKind::kAccessorOrMethod); if (IsArrowFunction(kind)) { if (IsAsyncFunction(kind)) { @@ -906,7 +933,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, // not passing the ScopeInfo to the Scope constructor. SetLanguageMode(scope, info->language_mode()); - scope->set_start_position(info->start_position()); + scope->set_start_position(start_position); ParserFormalParameters formals(scope); { ParameterDeclarationParsingScope formals_scope(this); @@ -927,14 +954,14 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, formals.duplicate_loc = formals_scope.duplicate_location(); } - if (GetLastFunctionLiteralId() != info->function_literal_id() - 1) { + if (GetLastFunctionLiteralId() != function_literal_id - 1) { if (has_error()) return nullptr; // If there were FunctionLiterals in the parameters, we need to // renumber them to shift down so the next function literal id for // the arrow function is the one requested. AstFunctionLiteralIdReindexer reindexer( stack_limit_, - (info->function_literal_id() - 1) - GetLastFunctionLiteralId()); + (function_literal_id - 1) - GetLastFunctionLiteralId()); for (auto p : formals.params) { if (p->pattern != nullptr) reindexer.Reindex(p->pattern); if (p->initializer() != nullptr) { @@ -942,7 +969,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, } } ResetFunctionLiteralId(); - SkipFunctionLiterals(info->function_literal_id() - 1); + SkipFunctionLiterals(function_literal_id - 1); } Expression* expression = ParseArrowFunctionLiteral(formals); @@ -952,7 +979,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, // concise body happens to be a valid expression. This is a problem // only for arrow functions with single expression bodies, since there // is no end token such as "}" for normal functions. - if (scanner()->location().end_pos == info->end_position()) { + if (scanner()->location().end_pos == end_position) { // The pre-parser saw an arrow function here, so the full parser // must produce a FunctionLiteral. DCHECK(expression->IsFunctionLiteral()); @@ -961,7 +988,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, } else if (IsDefaultConstructor(kind)) { DCHECK_EQ(scope(), outer); result = DefaultConstructor(raw_name, IsDerivedConstructor(kind), - info->start_position(), info->end_position()); + start_position, end_position); } else { ZonePtrList<const AstRawString>* arguments_for_wrapped_function = info->is_wrapped_as_function() @@ -969,24 +996,23 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, : nullptr; result = ParseFunctionLiteral( raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind, - kNoSourcePosition, info->function_syntax_kind(), + kNoSourcePosition, flags().function_syntax_kind(), info->language_mode(), arguments_for_wrapped_function); } if (has_error()) return nullptr; result->set_requires_instance_members_initializer( - info->requires_instance_members_initializer()); + flags().requires_instance_members_initializer()); result->set_class_scope_has_private_brand( - info->class_scope_has_private_brand()); + flags().class_scope_has_private_brand()); result->set_has_static_private_methods_or_accessors( - info->has_static_private_methods_or_accessors()); - if (info->is_oneshot_iife()) { + flags().has_static_private_methods_or_accessors()); + if (flags().is_oneshot_iife()) { result->mark_as_oneshot_iife(); } } - DCHECK_IMPLIES(result, - info->function_literal_id() == result->function_literal_id()); + DCHECK_IMPLIES(result, function_literal_id == result->function_literal_id()); return result; } @@ -1007,8 +1033,9 @@ Statement* Parser::ParseModuleItem() { // We must be careful not to parse a dynamic import expression as an import // declaration. Same for import.meta expressions. Token::Value peek_ahead = PeekAhead(); - if ((!allow_harmony_dynamic_import() || peek_ahead != Token::LPAREN) && - (!allow_harmony_import_meta() || peek_ahead != Token::PERIOD)) { + if ((!flags().allow_harmony_dynamic_import() || + peek_ahead != Token::LPAREN) && + (!flags().allow_harmony_import_meta() || peek_ahead != Token::PERIOD)) { ParseImportDeclaration(); return factory()->EmptyStatement(); } @@ -1068,7 +1095,7 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause( // caller needs to report an error. if (!reserved_loc->IsValid() && !Token::IsValidIdentifier(name_tok, LanguageMode::kStrict, false, - parsing_module_)) { + flags().is_module())) { *reserved_loc = scanner()->location(); } const AstRawString* local_name = ParsePropertyName(); @@ -1124,7 +1151,7 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) { } if (!Token::IsValidIdentifier(scanner()->current_token(), LanguageMode::kStrict, false, - parsing_module_)) { + flags().is_module())) { ReportMessage(MessageTemplate::kUnexpectedReserved); return nullptr; } else if (IsEvalOrArguments(local_name)) { @@ -1562,7 +1589,7 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name, bool was_added; Declare(declaration, variable_name, kind, mode, kCreatedInitialized, scope(), &was_added, beg_pos); - if (info()->coverage_enabled()) { + if (info()->flags().coverage_enabled()) { // Force the function to be allocated when collecting source coverage, so // that even dead functions get source coverage data. declaration->var()->set_is_used(); @@ -2378,7 +2405,7 @@ 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(parse_lazily(), info()->allow_lazy_compile()); + DCHECK_IMPLIES(parse_lazily(), info()->flags().allow_lazy_compile()); DCHECK_IMPLIES(parse_lazily(), has_error() || allow_lazy_); DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr); @@ -2477,7 +2504,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ? (is_top_level ? "preparse-no-resolution" : "preparse-resolution") : "full-parse"; logger_->FunctionEvent( - event_name, script_id(), ms, scope->start_position(), + event_name, flags().script_id(), ms, scope->start_position(), scope->end_position(), reinterpret_cast<const char*>(function_name->raw_data()), function_name->byte_length()); @@ -2584,7 +2611,7 @@ bool Parser::SkipFunction(const AstRawString* function_name, FunctionKind kind, PreParser::PreParseResult result = reusable_preparser()->PreParseFunction( function_name, kind, function_syntax_kind, function_scope, use_counts_, - produced_preparse_data, this->script_id()); + produced_preparse_data); if (result == PreParser::kPreParseStackOverflow) { // Propagate stack overflow. @@ -2733,6 +2760,7 @@ void Parser::ParseFunction( bool* has_duplicate_parameters, int* expected_property_count, int* suspend_count, ZonePtrList<const AstRawString>* arguments_for_wrapped_function) { + FunctionParsingScope function_parsing_scope(this); ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); FunctionState function_state(&function_state_, &scope_, function_scope); @@ -2880,7 +2908,7 @@ void Parser::DeclarePrivateClassMember(ClassScope* scope, ClassLiteralProperty::Kind kind, bool is_static, ClassInfo* class_info) { DCHECK_IMPLIES(kind != ClassLiteralProperty::Kind::FIELD, - allow_harmony_private_methods()); + flags().allow_harmony_private_methods()); if (kind == ClassLiteralProperty::Kind::FIELD) { if (is_static) { @@ -3085,11 +3113,11 @@ void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) { total_preparse_skipped_); } -void Parser::ParseOnBackground(ParseInfo* info) { +void Parser::ParseOnBackground(ParseInfo* info, int start_position, + int end_position, int function_literal_id) { RuntimeCallTimerScope runtimeTimer( runtime_call_stats_, RuntimeCallCounterId::kParseBackgroundProgram); parsing_on_main_thread_ = false; - set_script_id(info->script_id()); DCHECK_NULL(info->literal()); FunctionLiteral* result = nullptr; @@ -3104,19 +3132,19 @@ 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_toplevel()) { + if (flags().is_toplevel()) { + DCHECK_EQ(start_position, 0); + DCHECK_EQ(end_position, 0); + DCHECK_EQ(function_literal_id, kFunctionLiteralIdTopLevel); result = DoParseProgram(/* isolate = */ nullptr, info); } else { - result = - DoParseFunction(/* isolate = */ nullptr, info, info->function_name()); + result = DoParseFunction(/* isolate = */ nullptr, info, start_position, + end_position, function_literal_id, + info->function_name()); } MaybeResetCharacterStream(info, result); MaybeProcessSourceRanges(info, result, stack_limit_); - - info->set_literal(result); - - // We cannot internalize on a background thread; a foreground task will take - // care of calling AstValueFactory::Internalize just before compilation. + PostProcessParseResult(/* isolate = */ nullptr, info, result); } Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index fd24ffb3e8..472c9a71ab 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -14,6 +14,7 @@ #include "src/base/compiler-specific.h" #include "src/base/threaded-list.h" #include "src/common/globals.h" +#include "src/parsing/parse-info.h" #include "src/parsing/parser-base.h" #include "src/parsing/parsing.h" #include "src/parsing/preparser.h" @@ -134,7 +135,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { static bool IsPreParser() { return false; } - void ParseOnBackground(ParseInfo* info); + // Sets the literal on |info| if parsing succeeded. + void ParseOnBackground(ParseInfo* info, int start_position, int end_position, + int function_literal_id); // Initializes an empty scope chain for top-level scripts, or scopes which // consist of only the native context. @@ -207,14 +210,20 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { void PrepareGeneratorVariables(); - // Returns nullptr if parsing failed. - FunctionLiteral* ParseProgram(Isolate* isolate, Handle<Script> script, - ParseInfo* info, - MaybeHandle<ScopeInfo> maybe_outer_scope_info); + // Sets the literal on |info| if parsing succeeded. + void ParseProgram(Isolate* isolate, Handle<Script> script, ParseInfo* info, + MaybeHandle<ScopeInfo> maybe_outer_scope_info); + + // Sets the literal on |info| if parsing succeeded. + void ParseFunction(Isolate* isolate, ParseInfo* info, + Handle<SharedFunctionInfo> shared_info); + + void PostProcessParseResult(Isolate* isolate, ParseInfo* info, + FunctionLiteral* literal); - FunctionLiteral* ParseFunction(Isolate* isolate, ParseInfo* info, - Handle<SharedFunctionInfo> shared_info); FunctionLiteral* DoParseFunction(Isolate* isolate, ParseInfo* info, + int start_position, int end_position, + int function_literal_id, const AstRawString* raw_name); // Called by ParseProgram after setting up the scanner. @@ -239,15 +248,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { if (reusable_preparser_ == nullptr) { reusable_preparser_ = new PreParser( &preparser_zone_, &scanner_, stack_limit_, ast_value_factory(), - pending_error_handler(), runtime_call_stats_, logger_, -1, - parsing_module_, parsing_on_main_thread_); -#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); - SET_ALLOW(natives); - SET_ALLOW(harmony_dynamic_import); - SET_ALLOW(harmony_import_meta); - SET_ALLOW(harmony_private_methods); - SET_ALLOW(eval_cache); -#undef SET_ALLOW + pending_error_handler(), runtime_call_stats_, logger_, flags(), + parsing_on_main_thread_); + reusable_preparser_->set_allow_eval_cache(allow_eval_cache()); preparse_data_buffer_.reserve(128); } return reusable_preparser_; diff --git a/deps/v8/src/parsing/parsing.cc b/deps/v8/src/parsing/parsing.cc index 8a960cdc29..e126874d7d 100644 --- a/deps/v8/src/parsing/parsing.cc +++ b/deps/v8/src/parsing/parsing.cc @@ -12,6 +12,7 @@ #include "src/objects/objects-inl.h" #include "src/parsing/parse-info.h" #include "src/parsing/parser.h" +#include "src/parsing/rewriter.h" #include "src/parsing/scanner-character-streams.h" #include "src/zone/zone-list-inl.h" // crbug.com/v8/8816 @@ -19,10 +20,27 @@ namespace v8 { namespace internal { namespace parsing { +namespace { + +void MaybeReportErrorsAndStatistics(ParseInfo* info, Handle<Script> script, + Isolate* isolate, Parser* parser, + ReportErrorsAndStatisticsMode mode) { + if (mode == ReportErrorsAndStatisticsMode::kYes) { + if (info->literal() == nullptr) { + info->pending_error_handler()->PrepareErrors(isolate, + info->ast_value_factory()); + info->pending_error_handler()->ReportErrors(isolate, script); + } + parser->UpdateStatistics(isolate, script); + } +} + +} // namespace + bool ParseProgram(ParseInfo* info, Handle<Script> script, MaybeHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate, ReportErrorsAndStatisticsMode mode) { - DCHECK(info->is_toplevel()); + DCHECK(info->flags().is_toplevel()); DCHECK_NULL(info->literal()); VMState<PARSER> state(isolate); @@ -36,27 +54,11 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script, Parser parser(info); - FunctionLiteral* result = nullptr; // Ok to use Isolate here; this function is only called in the main thread. DCHECK(parser.parsing_on_main_thread_); - - result = parser.ParseProgram(isolate, script, info, maybe_outer_scope_info); - info->set_literal(result); - if (result) { - info->set_language_mode(info->literal()->language_mode()); - if (info->is_eval()) { - info->set_allow_eval_cache(parser.allow_eval_cache()); - } - } - - if (mode == ReportErrorsAndStatisticsMode::kYes) { - if (result == nullptr) { - info->pending_error_handler()->ReportErrors(isolate, script, - info->ast_value_factory()); - } - parser.UpdateStatistics(isolate, script); - } - return (result != nullptr); + parser.ParseProgram(isolate, script, info, maybe_outer_scope_info); + MaybeReportErrorsAndStatistics(info, script, isolate, &parser, mode); + return info->literal() != nullptr; } bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate, @@ -66,10 +68,12 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate, bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info, Isolate* isolate, ReportErrorsAndStatisticsMode mode) { - DCHECK(!info->is_toplevel()); + DCHECK(!info->flags().is_toplevel()); DCHECK(!shared_info.is_null()); DCHECK_NULL(info->literal()); + VMState<PARSER> state(isolate); + // Create a character stream for the parser. Handle<Script> script(Script::cast(shared_info->script()), isolate); Handle<String> source(String::cast(script->source()), isolate); @@ -79,37 +83,19 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info, shared_info->EndPosition())); info->set_character_stream(std::move(stream)); - VMState<PARSER> state(isolate); - Parser parser(info); - FunctionLiteral* result = nullptr; // Ok to use Isolate here; this function is only called in the main thread. DCHECK(parser.parsing_on_main_thread_); - - result = parser.ParseFunction(isolate, info, shared_info); - info->set_literal(result); - if (result) { - info->ast_value_factory()->Internalize(isolate); - if (info->is_eval()) { - info->set_allow_eval_cache(parser.allow_eval_cache()); - } - } - - if (mode == ReportErrorsAndStatisticsMode::kYes) { - if (result == nullptr) { - info->pending_error_handler()->ReportErrors(isolate, script, - info->ast_value_factory()); - } - parser.UpdateStatistics(isolate, script); - } - return (result != nullptr); + parser.ParseFunction(isolate, info, shared_info); + MaybeReportErrorsAndStatistics(info, script, isolate, &parser, mode); + return info->literal() != nullptr; } bool ParseAny(ParseInfo* info, Handle<SharedFunctionInfo> shared_info, Isolate* isolate, ReportErrorsAndStatisticsMode mode) { DCHECK(!shared_info.is_null()); - if (info->is_toplevel()) { + if (info->flags().is_toplevel()) { MaybeHandle<ScopeInfo> maybe_outer_scope_info; if (shared_info->HasOuterScopeInfo()) { maybe_outer_scope_info = diff --git a/deps/v8/src/parsing/pending-compilation-error-handler.cc b/deps/v8/src/parsing/pending-compilation-error-handler.cc index 80d201d13f..f131b7ad8e 100644 --- a/deps/v8/src/parsing/pending-compilation-error-handler.cc +++ b/deps/v8/src/parsing/pending-compilation-error-handler.cc @@ -5,24 +5,68 @@ #include "src/parsing/pending-compilation-error-handler.h" #include "src/ast/ast-value-factory.h" +#include "src/base/logging.h" #include "src/debug/debug.h" #include "src/execution/isolate.h" #include "src/execution/messages.h" +#include "src/execution/off-thread-isolate.h" #include "src/handles/handles.h" +#include "src/heap/off-thread-factory-inl.h" #include "src/objects/objects-inl.h" namespace v8 { namespace internal { +void PendingCompilationErrorHandler::MessageDetails::SetString( + Handle<String> string, Isolate* isolate) { + DCHECK_NE(type_, kMainThreadHandle); + DCHECK_NE(type_, kOffThreadTransferHandle); + type_ = kMainThreadHandle; + arg_handle_ = string; +} + +void PendingCompilationErrorHandler::MessageDetails::SetString( + Handle<String> string, OffThreadIsolate* isolate) { + DCHECK_NE(type_, kMainThreadHandle); + DCHECK_NE(type_, kOffThreadTransferHandle); + type_ = kOffThreadTransferHandle; + arg_transfer_handle_ = isolate->TransferHandle(string); +} + +template <typename LocalIsolate> +void PendingCompilationErrorHandler::MessageDetails::Prepare( + LocalIsolate* isolate) { + switch (type_) { + case kAstRawString: + return SetString(arg_->string(), isolate); + case kNone: + case kConstCharString: + // We can delay allocation until ArgumentString(isolate). + // TODO(leszeks): We don't actually have to transfer this string, since + // it's a root. + return; + case kMainThreadHandle: + case kOffThreadTransferHandle: + UNREACHABLE(); + } +} + Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString( Isolate* isolate) const { - if (arg_ != nullptr) return arg_->string(); - if (char_arg_ != nullptr) { - return isolate->factory() - ->NewStringFromUtf8(CStrVector(char_arg_)) - .ToHandleChecked(); + switch (type_) { + case kMainThreadHandle: + return arg_handle_; + case kOffThreadTransferHandle: + return arg_transfer_handle_.ToHandle(); + case kNone: + return isolate->factory()->undefined_string(); + case kConstCharString: + return isolate->factory() + ->NewStringFromUtf8(CStrVector(char_arg_), AllocationType::kOld) + .ToHandleChecked(); + case kAstRawString: + UNREACHABLE(); } - return isolate->factory()->undefined_string(); } MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation( @@ -37,8 +81,7 @@ void PendingCompilationErrorHandler::ReportMessageAt(int start_position, if (has_pending_error_) return; has_pending_error_ = true; - error_details_ = - MessageDetails(start_position, end_position, message, nullptr, arg); + error_details_ = MessageDetails(start_position, end_position, message, arg); } void PendingCompilationErrorHandler::ReportMessageAt(int start_position, @@ -48,8 +91,7 @@ void PendingCompilationErrorHandler::ReportMessageAt(int start_position, if (has_pending_error_) return; has_pending_error_ = true; - error_details_ = - MessageDetails(start_position, end_position, message, arg, nullptr); + error_details_ = MessageDetails(start_position, end_position, message, arg); } void PendingCompilationErrorHandler::ReportWarningAt(int start_position, @@ -57,11 +99,23 @@ void PendingCompilationErrorHandler::ReportWarningAt(int start_position, MessageTemplate message, const char* arg) { warning_messages_.emplace_front( - MessageDetails(start_position, end_position, message, nullptr, arg)); + MessageDetails(start_position, end_position, message, arg)); } -void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate, - Handle<Script> script) { +template <typename LocalIsolate> +void PendingCompilationErrorHandler::PrepareWarnings(LocalIsolate* isolate) { + DCHECK(!has_pending_error()); + + for (MessageDetails& warning : warning_messages_) { + warning.Prepare(isolate); + } +} +template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate); +template void PendingCompilationErrorHandler::PrepareWarnings( + OffThreadIsolate* isolate); + +void PendingCompilationErrorHandler::ReportWarnings( + Isolate* isolate, Handle<Script> script) const { DCHECK(!has_pending_error()); for (const MessageDetails& warning : warning_messages_) { @@ -75,27 +129,33 @@ void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate, } } -void PendingCompilationErrorHandler::ReportWarnings(OffThreadIsolate* isolate, - Handle<Script> script) { - // TODO(leszeks): Do nothing, re-report on the main thread. - UNREACHABLE(); +template <typename LocalIsolate> +void PendingCompilationErrorHandler::PrepareErrors( + LocalIsolate* isolate, AstValueFactory* ast_value_factory) { + if (stack_overflow()) return; + + DCHECK(has_pending_error()); + // Internalize ast values for throwing the pending error. + ast_value_factory->Internalize(isolate); + error_details_.Prepare(isolate); } +template void PendingCompilationErrorHandler::PrepareErrors( + Isolate* isolate, AstValueFactory* ast_value_factory); +template void PendingCompilationErrorHandler::PrepareErrors( + OffThreadIsolate* isolate, AstValueFactory* ast_value_factory); -void PendingCompilationErrorHandler::ReportErrors( - Isolate* isolate, Handle<Script> script, - AstValueFactory* ast_value_factory) { +void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate, + Handle<Script> script) const { if (stack_overflow()) { isolate->StackOverflow(); } else { DCHECK(has_pending_error()); - // Internalize ast values for throwing the pending error. - ast_value_factory->Internalize(isolate); ThrowPendingError(isolate, script); } } -void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate, - Handle<Script> script) { +void PendingCompilationErrorHandler::ThrowPendingError( + Isolate* isolate, Handle<Script> script) const { if (!has_pending_error_) return; MessageLocation location = error_details_.GetLocation(script); @@ -109,7 +169,8 @@ void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate, } Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest( - Isolate* isolate) const { + Isolate* isolate) { + error_details_.Prepare(isolate); return MessageFormatter::Format(isolate, error_details_.message(), error_details_.ArgumentString(isolate)); } diff --git a/deps/v8/src/parsing/pending-compilation-error-handler.h b/deps/v8/src/parsing/pending-compilation-error-handler.h index b854c3849e..4d15ac91ca 100644 --- a/deps/v8/src/parsing/pending-compilation-error-handler.h +++ b/deps/v8/src/parsing/pending-compilation-error-handler.h @@ -10,6 +10,7 @@ #include "src/base/macros.h" #include "src/common/globals.h" #include "src/common/message-template.h" +#include "src/execution/off-thread-isolate.h" #include "src/handles/handles.h" namespace v8 { @@ -47,15 +48,16 @@ class PendingCompilationErrorHandler { bool has_pending_warnings() const { return !warning_messages_.empty(); } // Handle errors detected during parsing. - void ReportErrors(Isolate* isolate, Handle<Script> script, - AstValueFactory* ast_value_factory); + template <typename LocalIsolate> + void PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory); + void ReportErrors(Isolate* isolate, Handle<Script> script) const; // Handle warnings detected during compilation. - void ReportWarnings(Isolate* isolate, Handle<Script> script); - void ReportWarnings(OffThreadIsolate* isolate, Handle<Script> script); + template <typename LocalIsolate> + void PrepareWarnings(LocalIsolate* isolate); + void ReportWarnings(Isolate* isolate, Handle<Script> script) const; - V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest( - Isolate* isolate) const; + V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest(Isolate* isolate); void set_unidentifiable_error() { has_pending_error_ = true; @@ -77,30 +79,54 @@ class PendingCompilationErrorHandler { : start_position_(-1), end_position_(-1), message_(MessageTemplate::kNone), - arg_(nullptr), - char_arg_(nullptr) {} + type_(kNone) {} MessageDetails(int start_position, int end_position, - MessageTemplate message, const AstRawString* arg, - const char* char_arg) + MessageTemplate message, const AstRawString* arg) : start_position_(start_position), end_position_(end_position), message_(message), arg_(arg), - char_arg_(char_arg) {} + type_(arg ? kAstRawString : kNone) {} + MessageDetails(int start_position, int end_position, + MessageTemplate message, const char* char_arg) + : start_position_(start_position), + end_position_(end_position), + message_(message), + char_arg_(char_arg), + type_(char_arg_ ? kConstCharString : kNone) {} Handle<String> ArgumentString(Isolate* isolate) const; MessageLocation GetLocation(Handle<Script> script) const; MessageTemplate message() const { return message_; } + template <typename LocalIsolate> + void Prepare(LocalIsolate* isolate); + private: + enum Type { + kNone, + kAstRawString, + kConstCharString, + kMainThreadHandle, + kOffThreadTransferHandle + }; + + void SetString(Handle<String> string, Isolate* isolate); + void SetString(Handle<String> string, OffThreadIsolate* isolate); + int start_position_; int end_position_; MessageTemplate message_; - const AstRawString* arg_; - const char* char_arg_; + union { + const AstRawString* arg_; + const char* char_arg_; + Handle<String> arg_handle_; + OffThreadTransferHandle<String> arg_transfer_handle_; + }; + Type type_; }; - void ThrowPendingError(Isolate* isolate, Handle<Script> script); + void ThrowPendingError(Isolate* isolate, Handle<Script> script) const; bool has_pending_error_; bool stack_overflow_; diff --git a/deps/v8/src/parsing/preparse-data-impl.h b/deps/v8/src/parsing/preparse-data-impl.h index 11165da5ed..707e76236d 100644 --- a/deps/v8/src/parsing/preparse-data-impl.h +++ b/deps/v8/src/parsing/preparse-data-impl.h @@ -158,17 +158,20 @@ class BaseConsumedPreparseData : public ConsumedPreparseData { LanguageMode* language_mode) final; void RestoreScopeAllocationData(DeclarationScope* scope, - AstValueFactory* ast_value_factory) final; + AstValueFactory* ast_value_factory, + Zone* zone) final; #ifdef DEBUG bool VerifyDataStart(); #endif private: - void RestoreDataForScope(Scope* scope, AstValueFactory* ast_value_factory); + void RestoreDataForScope(Scope* scope, AstValueFactory* ast_value_factory, + Zone* zone); void RestoreDataForVariable(Variable* var); void RestoreDataForInnerScopes(Scope* scope, - AstValueFactory* ast_value_factory); + AstValueFactory* ast_value_factory, + Zone* zone); std::unique_ptr<ByteData> scope_data_; // When consuming the data, these indexes point to the data we're going to diff --git a/deps/v8/src/parsing/preparse-data.cc b/deps/v8/src/parsing/preparse-data.cc index 7161861b76..d421cb868c 100644 --- a/deps/v8/src/parsing/preparse-data.cc +++ b/deps/v8/src/parsing/preparse-data.cc @@ -613,7 +613,7 @@ BaseConsumedPreparseData<Data>::GetDataForSkippableFunction( template <class Data> void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData( - DeclarationScope* scope, AstValueFactory* ast_value_factory) { + DeclarationScope* scope, AstValueFactory* ast_value_factory, Zone* zone) { DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE); typename ByteData::ReadingScope reading_scope(this); @@ -628,7 +628,7 @@ void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData( DCHECK_EQ(end_position_from_data, scope->end_position()); #endif - RestoreDataForScope(scope, ast_value_factory); + RestoreDataForScope(scope, ast_value_factory, zone); // Check that we consumed all scope data. DCHECK_EQ(scope_data_->RemainingBytes(), 0); @@ -636,7 +636,7 @@ void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData( template <typename Data> void BaseConsumedPreparseData<Data>::RestoreDataForScope( - Scope* scope, AstValueFactory* ast_value_factory) { + Scope* scope, AstValueFactory* ast_value_factory, Zone* zone) { if (scope->is_declaration_scope() && scope->AsDeclarationScope()->is_skipped_function()) { return; @@ -670,7 +670,7 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope( if (scope->AsClassScope()->is_anonymous_class()) { var = scope->AsClassScope()->DeclareClassVariable( ast_value_factory, nullptr, kNoSourcePosition); - AstNodeFactory factory(ast_value_factory, ast_value_factory->zone()); + AstNodeFactory factory(ast_value_factory, zone); Declaration* declaration = factory.NewVariableDeclaration(kNoSourcePosition); scope->declarations()->Add(declaration); @@ -692,7 +692,7 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope( if (IsSerializableVariableMode(var->mode())) RestoreDataForVariable(var); } - RestoreDataForInnerScopes(scope, ast_value_factory); + RestoreDataForInnerScopes(scope, ast_value_factory, zone); } template <typename Data> @@ -732,10 +732,10 @@ void BaseConsumedPreparseData<Data>::RestoreDataForVariable(Variable* var) { template <typename Data> void BaseConsumedPreparseData<Data>::RestoreDataForInnerScopes( - Scope* scope, AstValueFactory* ast_value_factory) { + Scope* scope, AstValueFactory* ast_value_factory, Zone* zone) { for (Scope* inner = scope->inner_scope(); inner != nullptr; inner = inner->sibling()) { - RestoreDataForScope(inner, ast_value_factory); + RestoreDataForScope(inner, ast_value_factory, zone); } } diff --git a/deps/v8/src/parsing/preparse-data.h b/deps/v8/src/parsing/preparse-data.h index 409942f8c3..aa31326f9f 100644 --- a/deps/v8/src/parsing/preparse-data.h +++ b/deps/v8/src/parsing/preparse-data.h @@ -134,8 +134,6 @@ class V8_EXPORT_PRIVATE PreparseDataBuilder : public ZoneObject, ByteData() : byte_data_(nullptr), index_(0), free_quarters_in_last_byte_(0) {} - ~ByteData() {} - void Start(std::vector<uint8_t>* buffer); void Finalize(Zone* zone); @@ -297,8 +295,9 @@ class ConsumedPreparseData { // Restores the information needed for allocating the Scope's (and its // subscopes') variables. - virtual void RestoreScopeAllocationData( - DeclarationScope* scope, AstValueFactory* ast_value_factory) = 0; + virtual void RestoreScopeAllocationData(DeclarationScope* scope, + AstValueFactory* ast_value_factory, + Zone* zone) = 0; protected: ConsumedPreparseData() = default; diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc index 464e8e7b17..f9af109d81 100644 --- a/deps/v8/src/parsing/preparser.cc +++ b/deps/v8/src/parsing/preparser.cc @@ -78,7 +78,7 @@ PreParser::PreParseResult PreParser::PreParseProgram() { // ModuleDeclarationInstantiation for Source Text Module Records creates a // new Module Environment Record whose outer lexical environment record is // the global scope. - if (parsing_module_) scope = NewModuleScope(scope); + if (flags().is_module()) scope = NewModuleScope(scope); FunctionState top_scope(&function_state_, &scope_, scope); original_scope_ = scope_; @@ -105,11 +105,9 @@ void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const { PreParser::PreParseResult PreParser::PreParseFunction( const AstRawString* function_name, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope, - int* use_counts, ProducedPreparseData** produced_preparse_data, - int script_id) { + int* use_counts, ProducedPreparseData** produced_preparse_data) { DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type()); use_counts_ = use_counts; - set_script_id(script_id); #ifdef DEBUG function_scope->set_is_being_lazily_parsed(true); #endif @@ -268,6 +266,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( int function_token_pos, FunctionSyntaxKind function_syntax_kind, LanguageMode language_mode, ZonePtrList<const AstRawString>* arguments_for_wrapped_function) { + FunctionParsingScope function_parsing_scope(this); // Wrapped functions are not parsed in the preparser. DCHECK_NULL(arguments_for_wrapped_function); DCHECK_NE(FunctionSyntaxKind::kWrapped, function_syntax_kind); @@ -358,7 +357,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( name_byte_length = string->byte_length(); } logger_->FunctionEvent( - event_name, script_id(), ms, function_scope->start_position(), + event_name, flags().script_id(), ms, function_scope->start_position(), function_scope->end_position(), name, name_byte_length); } diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h index 3c1122ef00..5280e3d226 100644 --- a/deps/v8/src/parsing/preparser.h +++ b/deps/v8/src/parsing/preparser.h @@ -8,6 +8,7 @@ #include "src/ast/ast-value-factory.h" #include "src/ast/ast.h" #include "src/ast/scopes.h" +#include "src/parsing/parse-info.h" #include "src/parsing/parser-base.h" #include "src/parsing/pending-compilation-error-handler.h" #include "src/parsing/preparser-logger.h" @@ -921,12 +922,11 @@ class PreParser : public ParserBase<PreParser> { AstValueFactory* ast_value_factory, PendingCompilationErrorHandler* pending_error_handler, RuntimeCallStats* runtime_call_stats, Logger* logger, - int script_id = -1, bool parsing_module = false, - bool parsing_on_main_thread = true) + UnoptimizedCompileFlags flags, bool parsing_on_main_thread = true) : ParserBase<PreParser>(zone, scanner, stack_limit, nullptr, ast_value_factory, pending_error_handler, - runtime_call_stats, logger, script_id, - parsing_module, parsing_on_main_thread), + runtime_call_stats, logger, flags, + parsing_on_main_thread), use_counts_(nullptr), preparse_data_builder_(nullptr), preparse_data_builder_buffer_() { @@ -954,8 +954,7 @@ class PreParser : public ParserBase<PreParser> { PreParseResult PreParseFunction( const AstRawString* function_name, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope, - int* use_counts, ProducedPreparseData** produced_preparser_scope_data, - int script_id); + int* use_counts, ProducedPreparseData** produced_preparser_scope_data); PreparseDataBuilder* preparse_data_builder() const { return preparse_data_builder_; diff --git a/deps/v8/src/parsing/rewriter.cc b/deps/v8/src/parsing/rewriter.cc index 75ec661d2d..942acf13f8 100644 --- a/deps/v8/src/parsing/rewriter.cc +++ b/deps/v8/src/parsing/rewriter.cc @@ -17,12 +17,12 @@ namespace internal { class Processor final : public AstVisitor<Processor> { public: Processor(uintptr_t stack_limit, DeclarationScope* closure_scope, - Variable* result, AstValueFactory* ast_value_factory) + Variable* result, AstValueFactory* ast_value_factory, Zone* zone) : result_(result), replacement_(nullptr), - zone_(ast_value_factory->zone()), + zone_(zone), closure_scope_(closure_scope), - factory_(ast_value_factory, ast_value_factory->zone()), + factory_(ast_value_factory, zone), result_assigned_(false), is_set_(false), breakable_(false) { @@ -31,10 +31,10 @@ class Processor final : public AstVisitor<Processor> { } Processor(Parser* parser, DeclarationScope* closure_scope, Variable* result, - AstValueFactory* ast_value_factory) + AstValueFactory* ast_value_factory, Zone* zone) : result_(result), replacement_(nullptr), - zone_(ast_value_factory->zone()), + zone_(zone), closure_scope_(closure_scope), factory_(ast_value_factory, zone_), result_assigned_(false), @@ -392,7 +392,7 @@ base::Optional<VariableProxy*> Rewriter::RewriteBody( Variable* result = scope->AsDeclarationScope()->NewTemporary( info->ast_value_factory()->dot_result_string()); Processor processor(info->stack_limit(), scope->AsDeclarationScope(), - result, info->ast_value_factory()); + result, info->ast_value_factory(), info->zone()); processor.Process(body); DCHECK_IMPLIES(scope->is_module_scope(), processor.result_assigned()); @@ -400,7 +400,7 @@ base::Optional<VariableProxy*> Rewriter::RewriteBody( int pos = kNoSourcePosition; VariableProxy* result_value = processor.factory()->NewVariableProxy(result, pos); - if (!info->is_repl_mode()) { + if (!info->flags().is_repl_mode()) { Statement* result_statement = processor.factory()->NewReturnStatement(result_value, pos); body->Add(result_statement, info->zone()); @@ -408,7 +408,10 @@ base::Optional<VariableProxy*> Rewriter::RewriteBody( return result_value; } - if (processor.HasStackOverflow()) return base::nullopt; + if (processor.HasStackOverflow()) { + info->pending_error_handler()->set_stack_overflow(); + return base::nullopt; + } } return nullptr; } diff --git a/deps/v8/src/parsing/scanner-inl.h b/deps/v8/src/parsing/scanner-inl.h index fc5194f263..bd4d0284d8 100644 --- a/deps/v8/src/parsing/scanner-inl.h +++ b/deps/v8/src/parsing/scanner-inl.h @@ -364,14 +364,14 @@ V8_INLINE Token::Value Scanner::ScanSingleToken() { return Select(token); case Token::CONDITIONAL: - // ? ?. ?? + // ? ?. ?? ??= Advance(); - if (V8_UNLIKELY(allow_harmony_optional_chaining() && c0_ == '.')) { + if (c0_ == '.') { Advance(); if (!IsDecimalDigit(c0_)) return Token::QUESTION_PERIOD; PushBack('.'); - } else if (V8_UNLIKELY(allow_harmony_nullish() && c0_ == '?')) { - return Select(Token::NULLISH); + } else if (c0_ == '?') { + return Select('=', Token::ASSIGN_NULLISH, Token::NULLISH); } return Token::CONDITIONAL; @@ -471,16 +471,16 @@ V8_INLINE Token::Value Scanner::ScanSingleToken() { return Token::DIV; case Token::BIT_AND: - // & && &= + // & && &= &&= Advance(); - if (c0_ == '&') return Select(Token::AND); + if (c0_ == '&') return Select('=', Token::ASSIGN_AND, Token::AND); if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND); return Token::BIT_AND; case Token::BIT_OR: - // | || |= + // | || |= ||= Advance(); - if (c0_ == '|') return Select(Token::OR); + if (c0_ == '|') return Select('=', Token::ASSIGN_OR, Token::OR); if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR); return Token::BIT_OR; diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc index 91e4183d53..52a1bf0724 100644 --- a/deps/v8/src/parsing/scanner.cc +++ b/deps/v8/src/parsing/scanner.cc @@ -13,6 +13,7 @@ #include "src/ast/ast-value-factory.h" #include "src/numbers/conversions-inl.h" #include "src/objects/bigint.h" +#include "src/parsing/parse-info.h" #include "src/parsing/scanner-inl.h" #include "src/zone/zone.h" @@ -89,12 +90,10 @@ bool Scanner::BookmarkScope::HasBeenApplied() const { // ---------------------------------------------------------------------------- // Scanner -Scanner::Scanner(Utf16CharacterStream* source, bool is_module) - : source_(source), +Scanner::Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags) + : flags_(flags), + source_(source), found_html_comment_(false), - allow_harmony_optional_chaining_(false), - allow_harmony_nullish_(false), - is_module_(is_module), octal_pos_(Location::invalid()), octal_message_(MessageTemplate::kNone) { DCHECK_NOT_NULL(source); @@ -190,7 +189,7 @@ Token::Value Scanner::PeekAhead() { } Token::Value Scanner::SkipSingleHTMLComment() { - if (is_module_) { + if (flags_.is_module()) { ReportScannerError(source_pos(), MessageTemplate::kHtmlCommentInModule); return Token::ILLEGAL; } @@ -233,9 +232,9 @@ void Scanner::TryToParseSourceURLComment() { if (!name.is_one_byte()) return; Vector<const uint8_t> name_literal = name.one_byte_literal(); LiteralBuffer* value; - if (name_literal == StaticCharVector("sourceURL")) { + if (name_literal == StaticOneByteVector("sourceURL")) { value = &source_url_; - } else if (name_literal == StaticCharVector("sourceMappingURL")) { + } else if (name_literal == StaticOneByteVector("sourceMappingURL")) { value = &source_mapping_url_; } else { return; diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h index bed63c9d4e..830067e1ad 100644 --- a/deps/v8/src/parsing/scanner.h +++ b/deps/v8/src/parsing/scanner.h @@ -15,6 +15,7 @@ #include "src/common/globals.h" #include "src/common/message-template.h" #include "src/parsing/literal-buffer.h" +#include "src/parsing/parse-info.h" #include "src/parsing/token.h" #include "src/strings/char-predicates.h" #include "src/strings/unicode.h" @@ -269,7 +270,7 @@ class V8_EXPORT_PRIVATE Scanner { static const int kNoOctalLocation = -1; static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput; - explicit Scanner(Utf16CharacterStream* source, bool is_module); + explicit Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags); void Initialize(); @@ -410,18 +411,6 @@ class V8_EXPORT_PRIVATE Scanner { bool FoundHtmlComment() const { return found_html_comment_; } - bool allow_harmony_optional_chaining() const { - return allow_harmony_optional_chaining_; - } - - void set_allow_harmony_optional_chaining(bool allow) { - allow_harmony_optional_chaining_ = allow; - } - - bool allow_harmony_nullish() const { return allow_harmony_nullish_; } - - void set_allow_harmony_nullish(bool allow) { allow_harmony_nullish_ = allow; } - const Utf16CharacterStream* stream() const { return source_; } private: @@ -715,6 +704,8 @@ class V8_EXPORT_PRIVATE Scanner { const TokenDesc& next() const { return *next_; } const TokenDesc& next_next() const { return *next_next_; } + UnoptimizedCompileFlags flags_; + TokenDesc* current_; // desc for current token (as returned by Next()) TokenDesc* next_; // desc for next token (one token look-ahead) TokenDesc* next_next_; // desc for the token after next (after PeakAhead()) @@ -730,12 +721,6 @@ class V8_EXPORT_PRIVATE Scanner { // Whether this scanner encountered an HTML comment. bool found_html_comment_; - // Harmony flags to allow ESNext features. - bool allow_harmony_optional_chaining_; - bool allow_harmony_nullish_; - - const bool is_module_; - // Values parsed from magic comments. LiteralBuffer source_url_; LiteralBuffer source_mapping_url_; diff --git a/deps/v8/src/parsing/token.h b/deps/v8/src/parsing/token.h index 4749945ebd..ef92238de2 100644 --- a/deps/v8/src/parsing/token.h +++ b/deps/v8/src/parsing/token.h @@ -31,6 +31,9 @@ namespace internal { /* Binary operators */ /* ADD and SUB are at the end since they are UnaryOp */ #define BINARY_OP_TOKEN_LIST(T, E) \ + E(T, NULLISH, "??", 3) \ + E(T, OR, "||", 4) \ + E(T, AND, "&&", 5) \ E(T, BIT_OR, "|", 6) \ E(T, BIT_XOR, "^", 7) \ E(T, BIT_AND, "&", 8) \ @@ -97,9 +100,6 @@ namespace internal { /* IsBinaryOp() relies on this block of enum values */ \ /* being contiguous and sorted in the same order! */ \ T(COMMA, ",", 1) \ - T(NULLISH, "??", 3) \ - T(OR, "||", 4) \ - T(AND, "&&", 5) \ \ /* Unary operators, starting at ADD in BINARY_OP_TOKEN_LIST */ \ /* IsUnaryOp() relies on this block of enum values */ \ @@ -297,8 +297,8 @@ class V8_EXPORT_PRIVATE Token { } static Value BinaryOpForAssignment(Value op) { - DCHECK(base::IsInRange(op, ASSIGN_BIT_OR, ASSIGN_SUB)); - Value result = static_cast<Value>(op - ASSIGN_BIT_OR + BIT_OR); + DCHECK(base::IsInRange(op, ASSIGN_NULLISH, ASSIGN_SUB)); + Value result = static_cast<Value>(op - ASSIGN_NULLISH + NULLISH); DCHECK(IsBinaryOp(result)); return result; } |