diff options
Diffstat (limited to 'deps/v8/src/parsing/parse-info.cc')
-rw-r--r-- | deps/v8/src/parsing/parse-info.cc | 360 |
1 files changed, 193 insertions, 167 deletions
diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc index 3723636804d..37432e05b7d 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) { |